﻿// Main Program

function BBSFox() {
    /*
    this.gBrowser=Components.classes["@mozilla.org/appshell/window-mediator;1"]
                  .getService(Components.interfaces.nsIWindowMediator)
                  .getMostRecentWindow("navigator:browser").gBrowser;

    this.os = Components.classes["@mozilla.org/xre/app-info;1"]
                 .getService(Components.interfaces.nsIXULRuntime).OS;
    */
    this.CmdHandler = document.getElementById('cmdHandler');
    this.CmdHandler.setAttribute(USE_MOUSE_BROWSING, '1');
    this.CmdHandler.setAttribute('doDOMMouseScroll', '0');
    //this.CmdHandler.setAttribute('useMouseUpDown', '0');
    //this.CmdHandler.setAttribute('useMouseSwitchPage', '0');
    //this.CmdHandler.setAttribute("useMouseReadThread", '0');
    this.CmdHandler.setAttribute(MOUSE_WHEEL_FUNC1, '1');
    this.CmdHandler.setAttribute(MOUSE_WHEEL_FUNC2, '2');
    this.CmdHandler.setAttribute(MOUSE_WHEEL_FUNC3, '0');
    this.CmdHandler.setAttribute('useTextDragAndDrop', '0');
    this.CmdHandler.setAttribute("HokeyForMouseBrowsing", '0');
    this.CmdHandler.setAttribute("EnableBackground", '1');
    this.CmdHandler.setAttribute('webContextMenu', '1');
    this.CmdHandler.setAttribute('SavePageMenu', '1');
    this.CmdHandler.setAttribute('EmbeddedPlayerMenu', '1');
    this.CmdHandler.setAttribute('PreviewPictureMenu', '0');
    this.CmdHandler.setAttribute('EasyReadingMenu', '0');
    this.CmdHandler.setAttribute('PushThreadMenu', '0');
    this.CmdHandler.setAttribute('OpenAllLinkMenu', '0');
    this.CmdHandler.setAttribute("MouseBrowseMenu", '0');
    this.CmdHandler.setAttribute("SwitchBgDisplayMenu", '0');
    this.CmdHandler.setAttribute('FileIoMenu', '0');
    this.CmdHandler.setAttribute('DownloadPostMenu', '0');
    this.CmdHandler.setAttribute('ScreenKeyboardMenu', '1');
    this.CmdHandler.setAttribute('ScreenKeyboardOpened', '0');
    this.CmdHandler.setAttribute('DragingWindow', '0');
    this.CmdHandler.setAttribute('MaxZIndex', 11);
    this.CmdHandler.setAttribute('allowDrag','0');
    this.CmdHandler.setAttribute('haveLink','0');
    //this.CmdHandler.setAttribute('onLink','0');
    //this.CmdHandler.setAttribute('onPicLink','0');
    this.CmdHandler.setAttribute('mouseOnPicWindow','0');
    this.CmdHandler.setAttribute('draging','0');
    this.CmdHandler.setAttribute('textSelected','0');
    this.CmdHandler.setAttribute('dragType','');
    this.CmdHandler.setAttribute('LastPicAddr', '0');
    this.CmdHandler.setAttribute('isMouseRightBtnDrag','0');

    this.CmdHandler.setAttribute('hideBookMarkLink','1');
    this.CmdHandler.setAttribute('hideSendLink','1');
    this.CmdHandler.setAttribute('hideBookMarkPage','1');
    this.CmdHandler.setAttribute('hideSendPage','1');
    this.CmdHandler.setAttribute('hideViewInfo','1');
    this.CmdHandler.setAttribute('SkipMouseClick','0');
    this.pref = null;

    this.telnetCore = new TelnetCore(this);
    this.view = new TermView(24);
    this.buf = new TermBuf(80, 24);
    /*
    this.playerMgr=new PlayerMgr();
    this.picViewerMgr=new PicViewerMgr();
    this.symbolinput=new SymbolInput();
    */
    this.buf.setView(this.view);
    //this.buf.severNotifyStr=this.getLM('messageNotify');
    //this.buf.PTTZSTR1=this.getLM('PTTZArea1');
    //this.buf.PTTZSTR2=this.getLM('PTTZArea2');
    this.view.setBuf(this.buf);
    this.view.setConn(this.telnetCore);
    this.view.setCore(this);
    this.parser = new AnsiParser(this.buf);
    /*
    var appInfo = Components.classes["@mozilla.org/xre/app-info;1"].getService(Components.interfaces.nsIXULAppInfo);
    this.FXVersion = parseFloat(appInfo.version);
    //new pref - start
    this.prefListener=null;
    this.isDefaultPref=true;
    */
    this.antiIdleStr='';
    this.antiIdleTime=0;
    this.deleteSpaceWhenCopy=true;
    this.loadURLInBG=false;
    this.clearCopiedSel=true;
    //new pref - end
    this.unusedTime = 0;
    this.connectTime = 0;
    this.connectState = 0;

    this.DocInputArea = document.getElementById('t');
    this.BBSWin = document.getElementById('BBSWindow');
    this.BBSBg = document.getElementById('BBSBackgroundImage');
    /*
    this.btnCloseSymbolInput = document.getElementById('btnCloseSymbolInput');

    this.asciitable = window.asciiTable;
    this.ctrlTable = window.ctrlTable;
    this.mouseLeftButtonDown = false;
    //this.mouseRightButtonDown = false;
    */
    this.DelayPasteBuffer = '';
    this.DelayPasteIndex = -1;
    this.DelayPasteNotify = true;

    this.LastMouseDownX = 0;
    this.LastMouseDownY = 0;
    //this.CanExecMouseDown = true;
    this.DragText = false;

    this.focusTimer = null;
    this.tabUpdateTimer = null;
    this.settingCheckTimer = null;
    this.inputAreaFocusTimer = null;
    //this.xmlhttp = null;
    //this.doDOMMouseScroll = false;
    this.post_text=new Array();
    this.post_html=new Array();
    this.tempFiles=[];
    this.downpostcounter = null;
    this.alertBeforeUnload = false;
    this.pushThreadLineLength = 70;
    this.pushTextTemp = '';

    /*
    this.tab_Select ={
        view: this,
        handleEvent: function(e) {
            this.view.focusTab(e);
        }
    };
    this.gBrowser.tabContainer.addEventListener("TabSelect", this.tab_Select, false);

    this.tab_AttrModified ={
        view: this,
        handleEvent: function(e) {
            this.view.tabAttrModified(e);
        }
    };
    if(this.FXVersion >= 4.0) //for firefox 4
      this.gBrowser.tabContainer.addEventListener("TabAttrModified", this.tab_AttrModified, false);
    */
    var cmd_Listener ={
        bbsfox: this,
        handleEvent: function(e) {
            this.bbsfox.overlayCommandListener(e);
        }
    };
    this.CmdHandler.addEventListener("OverlayCommand", cmd_Listener, false);

    var mouseclick ={
        bbsfox: this,
        handleEvent: function(e) {
            this.bbsfox.mouse_click(e);
        }
    };
    window.addEventListener('click', mouseclick, false);

    var mousedowninit ={
        bbsfox: this,
        handleEvent: function(e) {
            this.bbsfox.mouse_down_init(e);
        }
    };
    window.addEventListener('mousedown', mousedowninit, true);

    var mousedown ={
        bbsfox: this,
        handleEvent: function(e) {
            this.bbsfox.mouse_down(e);
        }
    };
    window.addEventListener('mousedown', mousedown, false);

    var mouseup ={
        bbsfox: this,
        handleEvent: function(e) {
            this.bbsfox.mouse_up(e);
        }
    };
    window.addEventListener('mouseup', mouseup, false);

    var mousemove ={
        bbsfox: this,
        handleEvent: function(e) {
            this.bbsfox.mouse_move(e);
        }
    };
    document.addEventListener('mousemove', mousemove, false);

    var mouseover ={
        bbsfox: this,
        handleEvent: function(e) {
            this.bbsfox.mouse_over(e);
        }
    };
    document.addEventListener('mouseover', mouseover, false);

    var mousescroll ={
        bbsfox: this,
        handleEvent: function(e) {
            this.bbsfox.mouse_scroll(e);
        }
    };
    addEventListener('mousewheel', mousescroll, true);

    this.menuHandler = {};
    chrome.contextMenus.onClicked.addListener(function(onClickData, tab) {
      bbsfox.menuHandler[onClickData.menuItemId]();
    });

    var contextmenu ={
        bbsfox: this,
        handleEvent: function(e) {
            this.bbsfox.context_menu(e);
        }
    };
    window.addEventListener('contextmenu', contextmenu, false);

    /*
    var mousedragstart ={
        view: this,
        handleEvent: function(e) {
            this.view.DragText=true;
        }
    };
    document.addEventListener ('dragstart', mousedragstart, false);

    var mousedragover ={
        view: this,
        handleEvent: function(e) {
            this.view.mouse_dragover(e);
        }
    };
    document.addEventListener ('dragover', mousedragover, false);

    var mousedrop ={
        view: this,
        handleEvent: function(e) {
            this.view.mouse_dragdrop(e);
        }
    };
    document.addEventListener ('drop', mousedrop, false);

    var mousedragend ={
        view: this,
        handleEvent: function(e) {
            this.view.DragText=false;
        }
    };
    document.addEventListener ('dragend', mousedragend, false);
    */
    var keypress ={
        bbsfox: this,
        handleEvent: function(e) {
            this.bbsfox.key_press(e);
        }
    };
    //window.addEventListener('keypress', keypress, true);
    //window.addEventListener('keydown', keypress, true);

    this.view.fontResize();
    this.dblclickTimer=null;
    this.mouseDownTimer=null;
    this.mbTimer=null;

    /*
    window.controllers.insertControllerAt(0, this.documentControllers);            // to override default commands for window
    this.DocInputArea.controllers.insertControllerAt(0, this.documentControllers); // to override default commands for inputbox
    */
}

BBSFox.prototype={
    /*
    conv: Components.classes["@mozilla.org/intl/utf8converterservice;1"].getService(Components.interfaces.nsIUTF8ConverterService),
    timerOnsec: Components.classes["@mozilla.org/timer;1"].createInstance(Components.interfaces.nsITimer),
    //timerMinWindow: Components.classes["@mozilla.org/timer;1"].createInstance(Components.interfaces.nsITimer),

   _bundle: Components.classes["@mozilla.org/intl/stringbundle;1"].getService(Components.interfaces.nsIStringBundleService)
            .createBundle("chrome://bbsfox/locale/bbsfox.properties"),

    youtubeRegEx: /((http:\/\/www\.youtube\.com\/watch\?v=([A-Za-z0-9._%-]*))|(http:\/\/youtu\.be\/([A-Za-z0-9._%-]*)))/i,
    ustreamRegEx: /(http:\/\/www\.ustream\.tv\/(channel|channel-popup)\/([A-Za-z0-9._%-]*))/i,
    urecordRegEx: /(http:\/\/www\.ustream\.tv\/recorded\/([0-9]{5,10}))/i,
    //there are some problem: http://www.ustream.tv/xxx -> http://www.ustream.tv/channel/xxx

    documentControllers: {
      supportsCommand: function(cmd){
        switch (cmd) {
          case "cmd_undo":
          case "cmd_redo":
          case "cmd_cut":
          case "cmd_copy":
          case "cmd_paste":
          case "cmd_selectAll":
          case "cmd_delete":
          case "cmd_switchTextDirection":
          case "cmd_find":
          case "cmd_findAgain":
            return true;
        }
      },
      isCommandEnabled: function(cmd){
        switch (cmd) {
          case "cmd_copy":
            if(window.getSelection().isCollapsed) //not select anything
              return false;
          case "cmd_paste":
          case "cmd_selectAll":
            return true;
          default:
            return false;
        }
      },
      doCommand: function(cmd){
        switch (cmd) {
          case "cmd_undo":
          case "cmd_redo":
          case "cmd_cut":
            return true;
          case "cmd_copy":
            bbsfox.doCopySelect();
            break;
          case "cmd_paste":
            bbsfox.doPaste();
            break;
          case "cmd_selectAll":
            bbsfox.doSelectAll();
            break;
          case "cmd_delete":
          case "cmd_switchTextDirection":
          case "cmd_find":
          case "cmd_findAgain":
            return true;
        }
      },
      onEvent: function(e){ }
    },
    */
    reloadSetting: function() {
      this.pref.reloadSetting();
    },

    connect: function(url) {
      dumpLog(DUMP_TYPE_LOG, "connect to " + url);
      this.pref = new BBSFoxPref(this, url);
      document.title = this.pref.sitename;
      var splits = url.split(/:/g);
      var port = 23;
      if(splits.length == 1)
      {
      }
      else if(splits.length == 2)
      {
        url = splits[0];
        port = splits[1];
      }
      this.telnetCore.connect(url, port);
    },
    /*
    symbtnclick: function(e){
      if(this.connectState==1)
      {
        this.telnetCore.convSend(e.target.label, this.view.charset);
        this.setInputAreaFocus();
      }
    },

    //getLocalizedMessage
    getLM: function(msg) {
        return this._bundle.GetStringFromName(msg);
    },

    isPTT: function(address) {
        return (address=='ptt.cc' || address=='bbs.ptt.cc' || address=='ptt.twbbs.org');
    },
    */
    close: function() {
        /*
        window.controllers.removeController(this.documentControllers);            // to override default commands for window
        this.DocInputArea.controllers.removeController(this.documentControllers); // to override default commands for inputbox
        this.gBrowser.tabContainer.removeEventListener("TabSelect", this.tab_Select, false);
        if(this.FXVersion >= 4.0) //for firefox 4
          this.gBrowser.tabContainer.removeEventListener("TabAttrModified", this.tab_AttrModified, false);
        this.timerOnsec.cancel();
        */
        this.telnetCore.listener = null;
        this.telnetCore.close();
        /*
        this.buf.timerUpdate.cancel();
        */
        this.view.blinkTimeout.cancel();
        /*
        this.view.blinkTimeout = null;
        if(this.tabUpdateTimer)
        {
          this.tabUpdateTimer.cancel();
          this.tabUpdateTimer = null;
        }
        if(this.settingCheckTimer)
        {
          this.settingCheckTimer.cancel();
          this.settingCheckTimer = null;
        }
        */
        this.cancelMouseDownTimer();
        this.calcelMbTimer();
    },

    onConnect: function(telnetcore) {
    dumpLog(DUMP_TYPE_LOG, "bbsfox onConnect");
        this.connectState = 1;
        this.updateTabIcon('connect');
        this.unusedTime = 0;
        var _this=this;
        this.timerOnsec = setTimer(true, function(){_this.antiIdle();}, 1000);
    },

    onData: function(telnetcore, data) {
    //dumpLog(DUMP_TYPE_LOG, "bbsfox onData");
        this.parser.feed(data);
    },

    onClose: function(conn) {
    dumpLog(DUMP_TYPE_LOG, "bbsfox onClose");
        this.UnregExitAlert();

        this.connectState = 2;
        this.unusedTime = 0;

        this.updateTabIcon('disconnect');
        this.timerOnsec.cancel();
    },

    trim_left: function(str){
      var i;
      for(i=0;i<str.length;++i){
        if(str.charAt(i)!=" "&&str.charAt(i)!=" ") break;
      }
      str = str.substring(i,str.length);
      return str;
    },

    trim_right: function(str){
      var i;
      for(i=str.length-1;i>=0;i--){
        if(str.charAt(i)!=" "&&str.charAt(i)!=" ") break;
      }
      str = str.substring(0,i+1);
      return str;
    },

    trim_both: function(str){
      return this.trim_left(this.trim_right(str));
    },

    resetUnusedTime: function() {
      this.unusedTime = 0;
    },

    sendData: function(str) {
      if(this.connectState==1)
        this.telnetCore.convSend(str, this.view.charset);
    },

    sendCmdData: function(str) {
      if(this.connectState==1)
        this.telnetCore.send(str);
    },

    calcelMbTimer: function() {
      if(this.mbTimer)
      {
        this.mbTimer.cancel();
        this.mbTimer=null;
      }
    },

    setMbTimer: function() {
      this.calcelMbTimer();
      var _this=this;
      var func=function() {
        _this.mbTimer.cancel();
        _this.mbTimer=null;
        _this.CmdHandler.setAttribute('SkipMouseClick','0');
      }
      this.mbTimer = setTimer(false, func, 100);
    },

    calcelDblclickTimer: function() {
      if(this.dblclickTimer)
      {
        this.dblclickTimer.cancel();
        this.dblclickTimer=null;
      }
    },

    setDblclickTimer: function() {
      this.calcelDblclickTimer();
      var _this=this;
      var func=function() {
        _this.dblclickTimer.cancel();
        _this.dblclickTimer=null;
      }
      this.dblclickTimer = setTimer(false, func, 350);
    },

    cancelMouseDownTimer: function() {
      if(this.mouseDownTimer)
      {
        this.mouseDownTimer.cancel();
        this.mouseDownTimer=null;
      }
    },
    /*
    focusTab: function(event) {
      this.setInputAreaFocus();
    },

    tabAttrModified: function(event) {
      this.doReloadTabIcon(200);
    },
    */
    setInputAreaFocus: function() {
      //this.DocInputArea.disabled="";
      this.DocInputArea.focus();
    },
    /*
    setDelayInputAreaFocus: function() {
      if(this.dblclickTimer)
      {
        this.dblclickTimer.cancel();
        this.dblclickTimer=null;
      }
      var _this=this;
      var func=function() {
        _this.inputAreaFocusTimer.cancel();
        _this.inputAreaFocusTimer=null;
        _this.setInputAreaFocus();
      }
      this.inputAreaFocusTimer = this.view.myTimer(false, func, 1);
    },

    redraw: function() {
        var rows=this.buf.rows;
        var lines=this.buf.lines;
        for(var row=0; row<rows; ++row) {
            var line=lines[row];
            line[0].needUpdate = true;
        }
        this.buf.updateCharAttr();
        this.view.redraw(true);
        this.setInputAreaFocus();
    },

    doCopy: function(str) {
      //var clipboardHelper = Components.classes["@mozilla.org/widget/clipboardhelper;1"]
      //                                .getService(Components.interfaces.nsIClipboardHelper);
      if(this.deleteSpaceWhenCopy)
      {
        var strArray;

        if(this.os == 'WINNT')
          strArray = str.split('\r\n');
        else
          strArray = str.split('\n');

        str = '';
        for (var i=0 ;i<strArray.length ;i++)
        {
          str+=this.trim_right(strArray[i]);
          if(i<strArray.length-1)
            str+='\r\n';
        }
      }
      clipboardHelper.copyString(str);

      var evt = document.createEvent("HTMLEvents");
      evt.initEvent('copy', true, true);
      this.view.input.dispatchEvent(evt);
    },

    doCopySelect: function() {
      var selstr = window.getSelection().toString();
      this.doCopy(selstr);
      if(this.clearCopiedSel)
      {
        var sel = window.getSelection();
        if(sel.rangeCount > 0) sel.removeAllRanges();
        this.setInputAreaFocus();
      }
    },

    doDelayPasteText: function() {
      var clip = Components.classes["@mozilla.org/widget/clipboard;1"]
                            .getService(Components.interfaces.nsIClipboard);
      if(clip)
      {
        var trans = Components.classes["@mozilla.org/widget/transferable;1"]
                            .createInstance(Components.interfaces.nsITransferable);
        if (trans)
        {
          trans.addDataFlavor("text/unicode");
          clip.getData(trans, clip.kGlobalClipboard);
          var data={};
          var len={};
          trans.getTransferData("text/unicode", data, len);
          if(data && data.value) {
            var s=data.value.QueryInterface(Components.interfaces.nsISupportsString);
            s = s.data.substring(0, len.value / 2);
            s=s.replace(/\r\n/g, '\r');
            s=s.replace(/\n/g, '\r');
            //this.sendData(s);
            this.DelayPasteBuffer = s;
            this.DelayPasteIndex = 0;
          }
        }
      }
    },

    doPasteStr: function(s) {
        if(this.telnetCore) {
                s=s.replace(/\r\n/g, '\r');
                s=s.replace(/\n/g, '\r');
                s=s.replace(/\r/g, this.view.EnterChar);
                if(this.telnetCore.lineWrap && s.indexOf('\x1b') == -1)
                    this.telnetCore.lineWrapSend(s);
                else this.telnetCore.convSend(s, this.view.charset);
        }
    },
    */
    doPaste: function(){
      this.pasting = true;
      this.setInputAreaFocus();
      document.execCommand("paste", false, null);
      this.pasting = false;
    },
    /*
    getSelectStr: function() {
      var selstr = window.getSelection().toString();
      return selstr;
    },
    */
    doSelectAll: function() {
      //var allspans = document.getElementById("main");
      window.getSelection().selectAllChildren(this.view.mainDisplay);
    },
    /*
    doCopyHtml: function() {
      var clipboardHelper = Components.classes["@mozilla.org/widget/clipboardhelper;1"]
                                       .getService(Components.interfaces.nsIClipboardHelper);
      clipboardHelper.copyString(this.getPageSourceCode());
    },

    doSavePage: function() {
      this.saveDialog(this.getPageSourceCode());
    },

    saveDialog: function(data) {
      var nsIFilePicker = Components.interfaces.nsIFilePicker;
      var fileChooser = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
      fileChooser.init(window, null, nsIFilePicker.modeSave);

      fileChooser.defaultExtension = 'html';
      fileChooser.defaultString = 'newhtml';
      fileChooser.appendFilters(nsIFilePicker.filterHTML);

      var result = fileChooser.show();

      //returnOK        0
      //returnCancel    1
      //returnReplace   2
      if (result != nsIFilePicker.returnCancel) {
        // file is nsIFile, data is a string
        var foStream = Components.classes["@mozilla.org/network/file-output-stream;1"].
                   createInstance(Components.interfaces.nsIFileOutputStream);

        if(fileChooser.file.exists()){fileChooser.file.remove(true);}
        fileChooser.file.create(fileChooser.file.NORMAL_FILE_TYPE, 0666);

        foStream.init(fileChooser.file, 0x02, 0x200, null);

        var converter = Components.classes["@mozilla.org/intl/converter-output-stream;1"].
                    createInstance(Components.interfaces.nsIConverterOutputStream);
        converter.init(foStream, "UTF-8", 0, 0);
        converter.writeString(data);
        converter.close(); // this closes foStream
      }
    },

    getPageSourceCode: function(){
      var selstr='';

      this.view.doBlink = false;
      this.view.blinkOn=true;
      this.buf.notify();

      var allLinks = document.getElementsByTagName('a');
      for (var i = 0; i < allLinks.length; i++)
        allLinks[i].removeAttribute('onclick');

      var fontFace = this.view.fontFace
      if(fontFace=="")
        fontFace = "MingLiu";
      selstr = '<?xml version="1.0" encoding="UTF-8"?><html><head><title></title><style type="text/css">';
      selstr += '.main {font-family: ';
      selstr += fontFace;
      selstr += ';font-size: ';
      selstr += this.view.chh;
      selstr += 'px;background-color: #000000;line-height: 100%; margin: 0px;textAlign:'
      selstr += this.view.mainDisplay.style.textAlign;
      selstr += ';width:';
      selstr += this.view.mainDisplay.style.width;
      selstr += ';}body{color:white;background-color: #000000;margin:0px;}a,a:link,a:visited,a:active,a:hover{border-bottom: 0px;text-decoration:none;}.BBSLine{display:inline;color:#C0C0C0;background-color:#000000;white-space: pre;}#BBSWindow{position:relative;width:';
      selstr += document.documentElement.clientWidth;
      selstr += 'px;height:';
      selstr += document.documentElement.clientHeight;
      selstr += 'px;overflow:hidden;}';
      for(var i=0;i<16;++i)
        for(var j=0;j<16;++j)
          selstr +='.q'+i+'b'+j+'{color:'+ termColors[i] + (j!=0?(';background-color:'+termColors[j]):'') + ';}';

      for(var i=0;i<16;++i)
        for(var j=0;j<16;++j)
        {
          selstr +='.q'+i+'q'+j+'{color:'+ termColors[j] +';position:relative;}';
          selstr +='.q'+i+'q'+j+':after{content:attr(t);position:absolute;left:0px;color:'+termColors[i]+';width:50%;text-shadow:'+termColors[i]+' 0 0 0px,'+termColors[i]+' 0 0 0px,'+termColors[i]+' 0 0 0px,'+termColors[i]+' 0 0 0px,'+termColors[i]+' 0 0 0px;overflow:hidden;}';
        }

      for(var i=0;i<16;++i)
        for(var j=0;j<16;++j)
          selstr +='.b'+i+'b'+j+'{background:-moz-linear-gradient(left,'+termColors[i]+' 50%,'+termColors[j]+' 50%);}';

      for(var i=0;i<16;++i)
        selstr +='.q'+i+'{color:'+termColors[i]+';}';

      for(var i=1;i<16;++i)
        selstr +='.b'+i+'{background-color:'+termColors[i]+';}';

      selstr += '</style></head><body><div id="BBSWindow"><div id="main" class="main">';
      selstr += this.view.mainDisplay.innerHTML;
      selstr +='</div></div></body></html>';
      this.view.doBlink = true;

      for (var i = 0; i < allLinks.length; i++)
      {
        if(this.loadURLInBG) //this is only for developer testing
          allLinks[i].setAttribute('onclick', "bbsfox.bgtab(event, this);" );
      }

      return selstr;
    },

    doClearTrack: function() {
      var keywords = this.view.trackKeyWordList;
      if(keywords.options.length==0)
        return;
      keywords.options.length = 0;
      this.redraw();
    },

    doAddTrack: function() {
      var selstr = window.getSelection().toString();
      var strArray = selstr.split('\r\n');

      selstr = this.trim_right(strArray[0]);
      var findflag = false;
      var keywords = this.view.trackKeyWordList;
      for (var i = 0; i < keywords.options.length; i++) {
        if (keywords.options[i].text == selstr){
          findflag = true;
          keywords.options[i].value = '#ff0000';
          break;
        }
      }
      if(findflag) // select text already in track list
      {
      }
      else
      {
        keywords.options.add(new Option(selstr,'#ff0000'));
      }
      this.redraw();
    },

    doDelTrack: function() {
      var selstr = window.getSelection().toString();
      var strArray = selstr.split('\r\n');

      selstr = this.trim_right(strArray[0]);
      var keywords = this.view.trackKeyWordList;
      for (var i = keywords.options.length - 1; i >=0 ; --i) {
        if (keywords.options[i].text == selstr){
          keywords.remove(i);
          break;
        }
      }
      this.redraw();
    },

    doOpenAllLink: function() {
      var allLinks = document.getElementsByTagName('a');
      var url;
      var charset = document.characterSet;
      for (var i = 0; i < allLinks.length; i++)
      {
        url = allLinks[i].getAttribute("href");
        this.gBrowser.loadOneTab(url, null, charset, null, true, false);
      }
    },
    */
    switchMouseBrowsing: function() {
      if(this.CmdHandler.getAttribute(USE_MOUSE_BROWSING)=='1')
      {
        this.CmdHandler.setAttribute(USE_MOUSE_BROWSING, '0');
        this.buf.useMouseBrowsing=false;
      }
      else
      {
        this.CmdHandler.setAttribute(USE_MOUSE_BROWSING, '1');
        this.buf.useMouseBrowsing=true;
      }

      if(!this.buf.useMouseBrowsing)
      {
        this.buf.BBSWin.style.cursor = 'auto';
        this.buf.clearHighlight();
        this.buf.mouseCursor=0;
        this.buf.nowHighlight=-1;
        this.buf.tempMouseCol=0;
        this.buf.tempMouseRow=0;
      }
      else
      {
        this.buf.SetPageState();
        this.buf.resetMousePos();
        this.view.redraw(true);
        this.view.updateCursorPos();
      }
      //this.view.showAlertMessage(document.title, this.buf.useMouseBrowsing?this.getLM('mouseBrowseOn'):this.getLM('mouseBrowseOff'));
    },
    /*
    switchBgDisplay: function() {
      var enableBackground = (this.CmdHandler.getAttribute("EnableBackground")=='1');
      if(enableBackground)
      {
        if(this.view.DisplayBackground)
        {
          this.view.DisplayBackground = false;
          this.BBSBg.style.display='none';
        }
        else
        {
          this.view.DisplayBackground = true;
          this.BBSBg.style.display='block';
        }
      }
    },

    checkFireGestureKey: function() {
      var doGesture = false;
      var actionkey = this.CmdHandler.getAttribute("FireGestureKey");
      this.CmdHandler.removeAttribute("FireGestureKey");
      if(actionkey==null)
        return;
      switch (actionkey) {
        case "Page Up":
          this.telnetCore.send('\x1b[5~');
          doGesture = true;
          break;
        case "Page Down":
          this.telnetCore.send('\x1b[6~');
          doGesture = true;
          break;
        case "End":
          this.telnetCore.send('\x1b[4~');
          doGesture = true;
          break;
        case "Home":
          this.telnetCore.send('\x1b[1~');
          doGesture = true;
          break;
        case "Arrow Left":
          this.telnetCore.send('\x1b[D');
          doGesture = true;
          break;
        case "Arrow Up":
          this.telnetCore.send('\x1b[A');
          doGesture = true;
          break;
        case "Arrow Right":
          this.telnetCore.send('\x1b[C');
          doGesture = true;
          break;
        case "Arrow Down":
          this.telnetCore.send('\x1b[B');
          doGesture = true;
          break;
        case "SymbolInput":
          if(this.symbolinput)
          {
            this.symbolinput.setCore(this);
            this.symbolinput.switchWindow();
          }
          doGesture = true;
          break;

        case "EmbeddedPlayer":
          if(this.playerMgr){
            var param = this.CmdHandler.getAttribute("EPURL");
            this.CmdHandler.removeAttribute("EPURL");
            var testresult = this.playerMgr.testURL(param);
            if(testresult==1)
              this.playerMgr.openYoutubeWindow(param);
            else if(testresult==2)
              this.playerMgr.openUstreamWindow(param);
            else if(testresult==3)
              this.playerMgr.openUrecordWindow(param);
          }
          break;
        case "CloseEmbeddedPlayer":
          if(this.playerMgr)
            this.playerMgr.closeAllEmbededPlayer();
          break;
        case "MinimizeEmbeddedPlayer":
          if(this.playerMgr)
            this.playerMgr.minimizeAllEmbededPlayer();
          break;
        case "RestroeEmbeddedPlayer":
          if(this.playerMgr)
            this.playerMgr.restoreAllEmbededPlayer();
          break;
        case "Copy":
          this.doCopySelect();
          doGesture = true;
          break;
        case "Paste":
          this.doPaste();
          doGesture = true;
          break;
        case "DelayPasteText":
          this.doDelayPasteText();
          doGesture = true;
          break;
        case "EasyReading":
          var _this = this;
          this.view.myTimer(false, function(){_this.downloadPost(true,true,true);}, 10);
          doGesture = true;
          break;
        case "PushThread":
          this.doPushThread();
          doGesture = true;
          break;
        case "DownloadPostText":
          var _this = this;
          this.view.myTimer(false, function(){_this.downloadPost(false,false,false);}, 10);
          doGesture = true;
          break;
        case "DownloadPostAnsi":
          var _this = this;
          this.view.myTimer(false, function(){_this.downloadPost(true,false,false);}, 10);
          doGesture = true;
          break;
        case "DownloadPostHtml":
          var _this = this;
          this.view.myTimer(false, function(){_this.downloadPost(true,true,false);}, 10);
          doGesture = true;
          break;
        case "LoadFile":
          this.buf.loadFile();
          doGesture = true;
          break;
        case "SaveFile":
          this.buf.saveFile();
          doGesture = true;
          break;
        case "SelectAll":
          this.doSelectAll();
          doGesture = false;
          break;
        case "SavePage":
          this.doSavePage();
          doGesture = true;
          break;
        case "OpenAllLink":
          this.doOpenAllLink();
          doGesture = true;
          break;
        case "SwitchMouseBrowsing":
          this.switchMouseBrowsing();
          doGesture = true;
          break;
        case "SwitchBgDisplay":
          this.switchBgDisplay();
          doGesture = true;
          break;
        case "SendTextData":
          var actionkeyEx = this.CmdHandler.getAttribute("FireGestureKeyEx");
          this.CmdHandler.removeAttribute("FireGestureKeyEx");
          actionkeyEx=actionkeyEx.replace(/\r\n/g, '\r');
          actionkeyEx=actionkeyEx.replace(/\n/g, '\r');
          actionkeyEx=actionkeyEx.replace(/\r/g, this.view.EnterChar);
          this.telnetCore.convSend(actionkeyEx, this.view.charset);
          doGesture = true;
          break;
        default:
          if(actionkey.indexOf('codestr,')==0){
            this.sendCodeStr(actionkey, 1);
          }
          else if(actionkey.indexOf('codestrEx,')==0)
          {
            var actionkeyEx = this.CmdHandler.getAttribute("FireGestureKeyEx");
            this.CmdHandler.removeAttribute("FireGestureKeyEx");
            var arr = actionkey.split(',');
            var arr2 = actionkeyEx.split(',');
            var searchStr = this.getSelectStr();
            var table = this.asciitable;
            for(var i=1;i<arr.length;i++){
              if(arr[i]!='')
              {
                if(arr[i].charCodeAt(0)==99) //char
                  this.telnetCore.convSend(arr[i].substr(1,arr[i].length), this.view.charset);
                else if(arr[i].charCodeAt(0)==120) //hexcode
                  this.telnetCore.send(arr[i].substr(1,arr[i].length));
                else if(arr[i].charCodeAt(0)==104) //hexcode
                {
                  if(code=table[arr[i].toLowerCase()])
                    this.telnetCore.send(code);
                }
              }
            }
            this.telnetCore.convSend(searchStr, this.view.charset);
            for(var i=1;i<arr2.length;i++){
              if(arr2[i]!=''){
                if(arr2[i].charCodeAt(0)==99) //char
                  this.telnetCore.convSend(arr2[i].substr(1,arr2[i].length), this.view.charset);
                else if(arr2[i].charCodeAt(0)==120) //hexcode
                  this.telnetCore.send(arr2[i].substr(1,arr2[i].length));
                else if(arr2[i].charCodeAt(0)==104) //hexcode
                {
                  if(code=table[arr2[i].toLowerCase()])
                    this.telnetCore.send(code);
                }
              }
            }
          }
          doGesture = true;
          break;
      }
      if(doGesture)
        this.setInputAreaFocus();
    },

    sendCodeStr: function(str, startIdx) {
      var arr = str.split(',');
      var table = this.asciitable;
      var lastcodetype = '';
      for(var i=startIdx;i<arr.length;i++)
      {
        if(arr[i]!='')
        {
          if(arr[i].charCodeAt(0)==99) //char
            this.telnetCore.convSend(arr[i].substr(1,arr[i].length), this.view.charset);
          else if(arr[i].charCodeAt(0)==120) //hexcode
          {
            //if(code=table[arr[i].toLowerCase()])
            this.telnetCore.send(arr[i].substr(1,arr[i].length));
          }
          else if(arr[i].charCodeAt(0)==104) //hexcode
          {
            if(code=table[arr[i].toLowerCase()])
              this.telnetCore.send(code);
          }
        }
      }
    },

    notify: function(timer) {
      //if(timer == this.timerOnsec)
        this.antiIdle();
    },
    */
    antiIdle: function() {
      if(this.antiIdleTime && this.unusedTime > this.antiIdleTime)
      {
        if(this.antiIdleStr!='' && this.connectState==1)
          this.telnetCore.send(this.antiIdleStr);
      }
      else
      {
        if(this.connectState==1)
          this.unusedTime+=1000;
      }

      if(this.DelayPasteBuffer != '' && this.DelayPasteIndex!=-1 && this.DelayPasteIndex < this.DelayPasteBuffer.length )
      {
        var s = this.DelayPasteBuffer.substr(this.DelayPasteIndex, 1);
        this.DelayPasteIndex++;
        this.sendData(s);
        if(this.DelayPasteIndex == this.DelayPasteBuffer.length)
        {
          this.DelayPasteBuffer = '';
          this.DelayPasteIndex = -1;
          if(this.DelayPasteNotify)
            this.view.showAlertMessage(document.title, this.getLM('delayPasteFinish'));
        }
      }

    },
    /*
    reloadTabIcon: function() {
      if(this.connectState==1)
        this.updateTabIcon('connect');
      else if(this.connectState==2)
        this.updateTabIcon('disconnect');
      else
        this.updateTabIcon('none');
    },

    doReloadTabIcon: function(t) {
        if(this.tabUpdateTimer)
          this.tabUpdateTimer.cancel();
        var _this=this;
        var func=function() {
                _this.tabUpdateTimer = null;
                _this.reloadTabIcon();
        }
        this.tabUpdateTimer = this.view.myTimer(false, func, t);
    },
    */
    updateTabIcon: function(aStatus) {
      var icon = 'icon/logo.png';
      switch (aStatus) {
        case 'connect':
          icon =  'icon/connect.png';
          this.setInputAreaFocus();
          break;
        case 'disconnect':
      dumpLog(DUMP_TYPE_LOG, "icon/disconnect.png");
          icon =  'icon/disconnect.png';
          break;
        case 'newmessage':  // Not used yet
          icon =  'icon/connect.png';
          break;
        case 'connecting':  // Not used yet
          icon =  'icon/connecting.gif';
        default:
      }

      var link = document.querySelector("link[rel~='icon']");
      if (!link) {
        link = document.createElement("link");
        link.setAttribute("rel", "icon");
        link.setAttribute("href", icon);
        document.head.appendChild(link);
      }
    else
    {
        link.setAttribute("href", icon);
    }
    },
    /*
    clientToCursor: function(cX, cY){
      var x = cX - parseFloat(this.view.firstGrid.offsetLeft);
      var y = cY - parseFloat(this.view.firstGrid.offsetTop);
      var col = Math.floor(x / this.view.chw);
      var row = Math.floor(y / this.view.chh);
      if(row >=0 && row < this.buf.rows && col >=0 && col < this.buf.cols){
        return {col: col, row: row};
      }
      else  // client Y out of "rows" range (it's possible since we don't resize canvas height to fit chh*24)
        return false;
    },
    */
    clientToPos: function(cX, cY){
      var x = cX - parseFloat(this.view.firstGrid.offsetLeft);
      var y = cY - parseFloat(this.view.firstGrid.offsetTop);
      var col = Math.floor(x / this.view.chw);
      var row = Math.floor(y / this.view.chh);

      if(row < 0)
        row = 0;
      else if(row >= this.buf.rows-1)
        row = this.buf.rows-1;

      if(col < 0)
        col = 0;
      else if(col >= this.buf.cols-1)
        col = this.buf.cols-1;

      return {col: col, row: row};
    },
    /*
    isOnURL: function(testrow, testcol){
      var cols=this.buf.cols;
      var rows=this.buf.rows;
      var lines = this.buf.lines;
      var chh = this.chh;

      var lines = this.buf.lines;
      var line = lines[testrow];
      var ch = line[testcol];
      return ch.isPartOfURL();
    },
    */
    onMouse_click: function(cX, cY){
          if(this.cancelDownloadAndPaste())
            return;
          switch (this.buf.mouseCursor) {
            case 1:
              this.telnetCore.send('\x1b[D');  //Arrow Left
              break;
            case 2:
              this.telnetCore.send('\x1b[5~'); //Page Up
              break;
            case 3:
              this.telnetCore.send('\x1b[6~'); //Page Down
              break;
            case 4:
              this.telnetCore.send('\x1b[1~'); //Home
              break;
            case 5:
              this.telnetCore.send('\x1b[4~'); //End
              break;
            case 6:
              if(this.buf.nowHighlight!=-1)
              {
                var sendstr = '';
                if(this.buf.cur_y > this.buf.nowHighlight)
                {
                  var count = this.buf.cur_y - this.buf.nowHighlight;
                  for(var i=0;i<count;++i)
                    sendstr+='\x1b[A'; //Arrow Up
                }
                else if(this.buf.cur_y < this.buf.nowHighlight)
                {
                  var count = this.buf.nowHighlight - this.buf.cur_y;
                  for(var i=0;i<count;++i)
                    sendstr+='\x1b[B'; //Arrow Down
                }
                sendstr+='\r';
                this.telnetCore.send(sendstr);
              }
              break;
            case 7:
              var pos = this.clientToPos(cX, cY);
              var sendstr = '';
              if(this.buf.cur_y > pos.row)
              {
                var count = this.buf.cur_y - pos.row;
                for(var i=0;i<count;++i)
                  sendstr+='\x1b[A'; //Arrow Up
              }
              else if(this.buf.cur_y < pos.row)
              {
                var count = pos.row - this.buf.cur_y;
                for(var i=0;i<count;++i)
                  sendstr+='\x1b[B'; //Arrow Down
              }
              sendstr+='\r';
              this.telnetCore.send(sendstr);
              break;
            case 0:
              this.telnetCore.send('\x1b[D'); //Arrow Left
              break;
            case 8:
              this.telnetCore.send('['); //Previous post with the same title
              break;
            case 9:
              this.telnetCore.send(']'); //Next post with the same title
              break;
            case 10:
              this.telnetCore.send('='); //First post with the same title
              break;
            case 12:
              this.telnetCore.send('\x1b[D\r\x1b[4~'); //Refresh post / pushed texts
              break;
            case 13:
              this.telnetCore.send('\x1b[D\r\x1b[4~[]'); //Last post with the same title (LIST)
              break;
            case 14:
              this.telnetCore.send('\x1b[D\x1b[4~[]\r'); //Last post with the same title (READING)
              break;
            default:
              //do nothing
              break;
          }
    },

    overlayCommandListener: function(event){
      var elm = event.target;
      var cmd = elm.getAttribute("bbsfoxCommand");
      dumpLog(DUMP_TYPE_LOG, cmd);
      if (elm){
        if(elm.id == 'cmdHandler') {
          switch (cmd) {
            case "doArrowUp":
              if(this.cancelDownloadAndPaste())
                return;
              this.telnetCore.send('\x1b[A');
              break;
            case "doArrowDown":
              if(this.cancelDownloadAndPaste())
                return;
              this.telnetCore.send('\x1b[B');
              break;
            case "doPageUp":
              if(this.cancelDownloadAndPaste())
                return;
              this.telnetCore.send('\x1b[5~');
              break;
            case "doPageDown":
              if(this.cancelDownloadAndPaste())
                return;
              this.telnetCore.send('\x1b[6~');
              break;
            case "cancelHoldMouse":
              this.cancelMouseDownTimer();
              break;
            case "prevousThread":
              if(this.cancelDownloadAndPaste())
                return;
              this.buf.SetPageState();
              if(this.buf.PageState==2 || this.buf.PageState==3 || this.buf.PageState==4)
              {
                this.cancelMouseDownTimer();
                this.telnetCore.send('[');
              }
              break;
            case "nextThread":
              if(this.cancelDownloadAndPaste())
                return;
              this.buf.SetPageState();
              if(this.buf.PageState==2 || this.buf.PageState==3 || this.buf.PageState==4)
              {
                this.cancelMouseDownTimer();
                this.telnetCore.send(']');
              }
              break;
            case "reloadTabIconDelay":
              this.doReloadTabIcon(100);
              break;
            case "reloadTabIcon":
              //alert('reloadTabIcon');
              this.reloadTabIcon();
              break;
            case "doAddTrack":
              this.doAddTrack();
              break;
            case "doDelTrack":
              this.doDelTrack();
              break;
            case "doClearTrack":
              this.doClearTrack();
              break;
            case "openSymbolInput":
              if(this.symbolinput)
              {
                this.symbolinput.setCore(this);
                this.symbolinput.displayWindow();
              }
              break;
            case "doSavePage":
              this.doSavePage();
              break;
            case "doCopyHtml":
              this.doCopyHtml();
              break;
            case "doSelectAll":
              this.doSelectAll();
              break;
            case "doCopy":
              this.doCopySelect();
              break;
            case "doPaste":
              this.doPaste();
              break;
            case "doDelayPasteText":
              this.doDelayPasteText();
              break;
            case "doOpenAllLink":
              this.doOpenAllLink();
              break;
            //case "doLoadUserSetting":
            //  this.doLoadUserSetting();
            //  break;
            case "switchMouseBrowsing":
              this.switchMouseBrowsing();
              break;
            case "switchBgDisplay":
              this.switchBgDisplay();
              break;
            case "checkFireGestureKey":
              if(this.cancelDownloadAndPaste())
                return;
              this.checkFireGestureKey();
              break;
            case "openYoutubeWindow":
              var param = elm.getAttribute("YoutubeURL");
              elm.removeAttribute("YoutubeURL");
              if(this.playerMgr)
                this.playerMgr.openYoutubeWindow(param);
              break;
            case "openUstreamWindow":
              var param = elm.getAttribute("UstreamURL");
              elm.removeAttribute("UstreamURL");
              if(this.playerMgr)
                this.playerMgr.openUstreamWindow(param);
              break;
            case "openUrecordWindow":
              var param = elm.getAttribute("UrecordURL");
              elm.removeAttribute("UrecordURL");
              if(this.playerMgr)
                this.playerMgr.openUrecordWindow(param);
              break;
            case "previewPicture":
              var param = elm.getAttribute("PictureURL");
              elm.removeAttribute("PictureURL");
              if(this.picViewerMgr)
                this.picViewerMgr.openPicture(param);
              break;
            case "doDownloadPost":
              var param = elm.getAttribute("DownloadColor");
              elm.removeAttribute("DownloadColor");
              if(param=='0')
                this.downloadPost(false,false,false);
              else if(param=='1')
                this.downloadPost(true,false,false);
              else// if(param=='2')
                this.downloadPost(true,true,false);
              break;
            case "doLoadFile":
              this.buf.loadFile();
              break;
            case "doSaveFile":
              this.buf.saveFile();
              break;
            case "checkPrefExist":
              this.doSiteSettingCheck(250);
              break;
            case "easyReading":
              this.downloadPost(true,true,true);
              break;
            case "pushThread":
              this.doPushThread();
              break;
            case "setAlert":
              var param = elm.getAttribute("AlertMessage");
              elm.removeAttribute("AlertMessage");
              //this.view.showAlertMessage(document.title, param);
              //alert(param);
              break;
            default:
              //e v a l("bbsfox."+cmd+"();"); //unsafe javascript? how to fix it?
              break;
          }
        }
        elm.removeAttribute("bbsfoxCommand");
      }
    },
    /*
    resetStatusBar: function(){
        //when view change, link url may be remove, we need updata statusbar.
        //wm.getMostRecentWindow("navigator:browser").XULBrowserWindow.updateStatusField();
        var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"].getService(Components.interfaces.nsIWindowMediator);
        wm.getMostRecentWindow("navigator:browser").XULBrowserWindow.setOverLink("");
    },
    */
    onMouse_move: function(cX, cY){
      var pos = this.clientToPos(cX, cY);
      this.buf.onMouse_move(pos.col, pos.row, false);
    },

    resetMouseCursor: function(cX, cY){
      this.buf.BBSWin.style.cursor = 'auto';
      this.buf.mouseCursor = 11;
    },

    clearHighlight: function(){
      this.buf.clearHighlight();
    },
    /*
    resetTabIcon: function() {
      this.doReloadTabIcon(10);
    },

    ////
    siteSettingCheck: function() {
      this.view.pictureWindow.style.display = 'none';
      this.CmdHandler.setAttribute('LastPicAddr','');
      var browserutils = new BBSFoxBrowserUtils();
      document.title = browserutils.findSiteTitle(document.location.hostname);
      if(bbsfox.isDefaultPref != browserutils.isDefaultPref)
      {
        bbsfox.prefListener.unregister();
        bbsfox.prefListener = browserutils.prefListener(function(branch, name) {
          bbsfox.onPrefChange(bbsfox, branch, name);
        });
        bbsfox.isDefaultPref = browserutils.isDefaultPref;
      }
    },
    */
    onPrefChange: function(pref, name) {
      try {
        //var CiStr = Components.interfaces.nsISupportsString;
    //dumpLog(DUMP_TYPE_LOG, "onPrefChange " + name + ":" + pref.getPrefValue(name));
        switch (name) {
        case MOUSE_WHEEL_FUNC1:
          this.CmdHandler.setAttribute(MOUSE_WHEEL_FUNC1, pref.getPrefValue(name));
          break;
        case MOUSE_WHEEL_FUNC2:
          this.CmdHandler.setAttribute(MOUSE_WHEEL_FUNC2, pref.getPrefValue(name));
          break;
        case MOUSE_WHEEL_FUNC3:
          this.CmdHandler.setAttribute(MOUSE_WHEEL_FUNC3, pref.getPrefValue(name));
          break;
        case USE_MOUSE_BROWSING:
          if(pref.getPrefValue(name))
          {
            this.CmdHandler.setAttribute(USE_MOUSE_BROWSING, '1');
            this.buf.useMouseBrowsing=true;
          }
          else
          {
            this.CmdHandler.setAttribute(USE_MOUSE_BROWSING, '0');
            this.buf.useMouseBrowsing=false;
          }
          if(!this.buf.useMouseBrowsing) {
            this.buf.BBSWin.style.cursor = 'auto';
            this.buf.clearHighlight();
            this.buf.mouseCursor=0;
            this.buf.nowHighlight=-1;
            this.buf.tempMouseCol=0;
            this.buf.tempMouseRow=0;
          }
          this.buf.SetPageState();
          this.buf.resetMousePos();
          this.view.redraw(true);
          this.view.updateCursorPos();
          break;
        case MOUSE_BROWSING_HIGH_LIGHT:
          this.buf.highlightCursor=pref.getPrefValue(name);
          this.view.redraw(true);
          this.view.updateCursorPos();
          break;
        case HIGHLIGHT_BG:
          this.view.highlightBG=pref.getPrefValue(name);
          if(this.view.highlightBG>15 || this.view.highlightBG<0)
            this.view.highlightBG = 2;
          //this.buf.highlightCursor=branch.getBoolPref(name);
          //this.view.redraw(true);
          //this.view.updateCursorPos();
          break;
        case MOUSE_BROWSING_HAND_POINTER:
          this.buf.handPointerCursor=pref.getPrefValue(name);
          break;
        case USE_MOUSE_BROWSING_EX:
          this.buf.useMouseBrowsingEx=pref.getPrefValue(name);
          //this.view.redraw(true);
          //this.view.updateCursorPos();
          break;
        case MOUSE_BROWSING_SEND_ENTER:
          this.view.useMouseBrowseSendEnter=pref.getPrefValue(name);
          break;
        case MIDDLE_BTN_FUNCTION:
          this.view.middleButtonFunction=pref.getPrefValue(name);
          break;
        case "DropToPaste":
          this.view.dropToPaste=branch.getBoolPref(name);
          break;
        case TERM_TYPE:
          this.telnetCore.termType=pref.getPrefValue(name);
          break;
        case BBS_SIZE:
          this.view.screenType = pref.getPrefValue(name);
          if(this.view.screenType==0)
          {
            this.view.bbsWidth = 0;
            this.view.bbsHeight = 0;
          }
          else if(this.view.screenType==1)
          {
            this.view.bbsWidth = pref.getPrefValue(VIEW_WIDTH);
            this.view.bbsHeight = pref.getPrefValue(VIEW_HEIGHT);
          }
          else// if(this.view.screenType==2)
          {
            this.view.bbsWidth = 0;
            this.view.bbsHeight = 0;
            this.view.bbsFontSize = pref.getPrefValue(VIEW_FONT_SIZE);
          }
          this.view.fontResize();
          this.view.updateCursorPos();
          break;
        case "FontSize":
          if(this.view.screenType==0)
          {
            this.view.bbsWidth = 0;
            this.view.bbsHeight = 0;
          }
          else if(this.view.screenType==1)
          {
            this.view.bbsWidth = branch.getIntPref('bbsbox.width');
            this.view.bbsHeight = branch.getIntPref('bbsbox.height');
          }
          else// if(this.view.screenType==2)
          {
            this.view.bbsWidth = 0;
            this.view.bbsHeight = 0;
            this.view.bbsFontSize = branch.getIntPref('FontSize');
            this.view.fontResize();
            this.view.updateCursorPos();
          }
          break;
        case "bbsbox.width":
        case "bbsbox.height":
          if(this.view.screenType==0)
          {
            this.view.bbsWidth = 0;
            this.view.bbsHeight = 0;
          }
          else if(this.view.screenType==1)
          {
            this.view.bbsWidth = branch.getIntPref('bbsbox.width');
            this.view.bbsHeight = branch.getIntPref('bbsbox.height');
            this.view.fontResize();
            this.view.updateCursorPos();
          }
          else// if(this.view.screenType==2)
          {
            this.view.bbsWidth = 0;
            this.view.bbsHeight = 0;
            this.view.bbsFontSize = branch.getIntPref('FontSize');
          }
          break;
        case "LoadUrlInBG":
          this.loadURLInBG=branch.getBoolPref(name);
          var allLinks = document.getElementsByTagName('a');
          for (var i = 0; i < allLinks.length; i++)
          {
            if(this.loadURLInBG) //this is only for developer testing
              allLinks[i].setAttribute('onclick', "bbsfox.bgtab(event, this);" );
            else
              allLinks[i].removeAttribute('onclick');
          }
          break;
        case "LineWrap":
          this.telnetCore.lineWrap=branch.getIntPref(name);
          break;
        case "LineFeed":
          this.buf.disableLinefeed=!branch.getBoolPref(name);
          break;
        case H_ALIGN_CENTER:
          if(pref.getPrefValue(name))
      this.view.BBSWin.setAttribute("align", "center");
          else
            this.view.BBSWin.setAttribute("align", "left");
          break;
        case V_ALIGN_CENTER:
          this.view.verticalAlignCenter = pref.getPrefValue(name);
          this.view.fontResize();
          break;
        case FONT_FACE:
          this.view.fontFace = pref.getPrefValue(name);
          if(!this.view.fontFace) this.view.fontFace='monospace';
          this.view.mainDisplay.style.fontFamily = this.view.fontFace;
          document.getElementById('cursor').style.fontFamily = this.view.fontFace;
          document.getElementById('BBSFoxFontTest').style.fontFamily = this.view.fontFace;
          break;
        case ESCAPE_STR:
          var str = pref.getPrefValue(name);
          this.telnetCore.EscChar = this.buf.parseText(str);
          break;
        case ENTER_TYPE:
          switch(pref.getPrefValue(name)) {
          case '1':
            this.view.EnterChar = '\r\n';
            break;
          case '0':
          default:
            this.view.EnterChar = '\r';
            break;
          }
          break;
        case "ClearCopiedSel":
          this.clearCopiedSel=branch.getBoolPref(name);
          break;
        case "Charset":
          //var charset=branch.getComplexValue(name, CiStr).data;
          if(charset=='locale') {
            charset = 'big5';
          }
          if(charset=='UTF-8' && (this.isPTT(document.location.hostname))) {
            this.buf.forceFullWidth = true;
          } else {
            this.buf.forceFullWidth = false;
          }
          this.view.charset = charset;
          this.view.redraw(true);
          break;
        case DBCS_DETECT:
          this.view.dbcsDetect=pref.getPrefValue(name);
          break;
        case CLOSE_QUERY:
          if(pref.getPrefValue(name))
            this.RegExitAlert();
          else
            this.UnregExitAlert();
          break;
        case DETECT_LINK:
          this.view.useHyperLink=pref.getPrefValue(name);
          if(this.view.useHyperLink)
          {
            //this.previewLink = prefs.getBoolPref('HyperLink.PreviewLink');
            //this.previewWithCtrl = prefs.getBoolPref('HyperLink.PreviewWithCtrl');
            //this.previerWindowHeight = prefs.getIntPref('HyperLink.PrevierWindowHeight');
          }
          else
          {
            //this.previewLink = false;
            //this.previewWithCtrl = false;
            //this.previerWindowHeight = 150;
          }
          this.view.redraw(true);
          break;
        case IDLE_STR:
          this.antiIdleStr = pref.getPrefValue(name);
          break;
        case IDLE_TIME:
          this.antiIdleTime = pref.getPrefValue(name) * 1000;
          //this.telnetCore.send();
          break;
        case HOTKEY_CTRL_W:
          this.view.hotkeyCtrlW = pref.getPrefValue(name);
          break;
        case "HotkeyCtrlB":
          this.view.hotkeyCtrlB = branch.getIntPref(name);
          break;
        case HOTKEY_CTRL_L:
          this.view.hotkeyCtrlL = pref.getPrefValue(name);
          break;
        case "HokeyForCopy":
          this.view.hokeyForCopy = branch.getBoolPref(name);
          break;
        case "HokeyForPaste":
          this.view.hokeyForPaste = branch.getBoolPref(name);
          break;
        case "Hokey2ForPaste":
          this.view.hokey2ForPaste = branch.getBoolPref(name);
          break;
        case HOKEY_FOR_SELECT_ALL:
          this.view.hokeyForSelectAll = pref.getPrefValue(name);
          break;
        case HOKEY_FR_MOUSE_BROWSING:
          if(pref.getPrefValue(name))
            this.CmdHandler.setAttribute("HokeyForMouseBrowsing", '1');
          else
            this.CmdHandler.setAttribute("HokeyForMouseBrowsing", '0');
          break;
        case HOKEY_FOR_EASY_READING:
          this.view.hokeyForEasyReading = pref.getPrefValue(name);
          break;
        case HOKEY_FOR_DOWNLOAD_POST:
          this.view.hokeyForDownloadPost = pref.getPrefValue(name);
          break;
        case HOTKEY_DOWNLOAD_TYPE:
          this.view.hotkeyDownloadType = pref.getPrefValue(name);
          break;
        case "SavePageMenu":
          if(branch.getBoolPref(name))
            this.CmdHandler.setAttribute("SavePageMenu", '1');
          else
            this.CmdHandler.setAttribute("SavePageMenu", '0');
          break;
        case "EmbeddedPlayerMenu":
          if(branch.getBoolPref(name))
            this.CmdHandler.setAttribute("EmbeddedPlayerMenu", '1');
          else
            this.CmdHandler.setAttribute("EmbeddedPlayerMenu", '0');
          break;
        case "PreviewPictureMenu":
          if(branch.getBoolPref(name))
            this.CmdHandler.setAttribute("PreviewPictureMenu", '1');
          else
            this.CmdHandler.setAttribute("PreviewPictureMenu", '0');
          break;
        case "ScreenKeyboardMenu":
          if(branch.getBoolPref(name))
            this.CmdHandler.setAttribute("ScreenKeyboardMenu", '1');
          else
            this.CmdHandler.setAttribute("ScreenKeyboardMenu", '0');
          break;
        case "OpenAllLinkMenu":
          if(branch.getBoolPref(name))
            this.CmdHandler.setAttribute("OpenAllLinkMenu", '1');
          else
            this.CmdHandler.setAttribute("OpenAllLinkMenu", '0');
          break;
        case "MouseBrowseMenu":
          if(branch.getBoolPref(name))
            this.CmdHandler.setAttribute("MouseBrowseMenu", '1');
          else
            this.CmdHandler.setAttribute("MouseBrowseMenu", '0');
          break;
        case "CopyHtmlMenu":
          if(branch.getBoolPref(name))
            this.CmdHandler.setAttribute("CopyHtmlMenu", '1');
          else
            this.CmdHandler.setAttribute("CopyHtmlMenu", '0');
          break;
        case "KeyWordTrackMenu":
          if(branch.getBoolPref(name))
            this.CmdHandler.setAttribute("KeyWordTrackMenu", '1');
          else
            this.CmdHandler.setAttribute("KeyWordTrackMenu", '0');
          break;
        case "DelayPasteMenu":
          if(branch.getBoolPref(name))
            this.CmdHandler.setAttribute("DelayPasteMenu", '1');
          else
            this.CmdHandler.setAttribute("DelayPasteMenu", '0');
          break;
        case "DownloadPostMenu":
          if(branch.getBoolPref(name))
            this.CmdHandler.setAttribute("DownloadPostMenu", '1');
          else
            this.CmdHandler.setAttribute("DownloadPostMenu", '0');
          break;
        case "EasyReadingMenu":
          if(branch.getBoolPref(name))
            this.CmdHandler.setAttribute("EasyReadingMenu", '1');
          else
            this.CmdHandler.setAttribute("EasyReadingMenu", '0');
          break;
        case "PushThreadMenu":
          if(branch.getBoolPref(name) && (this.isPTT(document.location.hostname)) )
            this.CmdHandler.setAttribute("PushThreadMenu", '1');
          else
            this.CmdHandler.setAttribute("PushThreadMenu", '0');
          break;
        case "FileIoMenu":
          if(branch.getBoolPref(name))
            this.CmdHandler.setAttribute("FileIoMenu", '1');
          else
            this.CmdHandler.setAttribute("FileIoMenu", '0');
          break;
        case "DownloadLineDelay":
          this.buf.downloadLineDelay=branch.getIntPref(name);
          break;
        case "SaveAfterDownload":
          this.buf.saveAfterDownload=branch.getBoolPref(name);
          break;
        case "EasyReadingWithImg":
          this.view.easyReadingWithImg=branch.getBoolPref(name);
          break;
        case "ScreenKeyboardAlpha":
          if(this.symbolinput)
            this.symbolinput.setWindowAlpha(branch.getIntPref(name));
          break;
        case "EmbeddedPlayerSize":
          if(this.playerMgr)
            this.playerMgr.setDefaultWindowSize(branch.getIntPref(name));
          break;
        case "EPAutoPlay":
          if(this.playerMgr)
            this.playerMgr.epAutoPlay = branch.getBoolPref(name);
          break;
        case "EPLoop":
          if(this.playerMgr)
            this.playerMgr.epLoop = branch.getBoolPref(name);
          break;
        case "EPAutoUseHQ":
          if(this.playerMgr)
            this.playerMgr.epAutoUseHQ = branch.getBoolPref(name);
          break;
        case "EPCopyUrlButton":
          if(this.playerMgr)
          {
            this.playerMgr.epCopyUrlButton = branch.getBoolPref(name);
            this.playerMgr.setAllEmbededPlayerUrlBtn(this.playerMgr.epCopyUrlButton);
          }
          break;
        case "EPWhenDropLink":
          if(this.playerMgr)
            this.playerMgr.epWhenDropLink = branch.getBoolPref(name);
          break;
        case "UseHttpContextMenu":
          if(branch.getBoolPref(name))
            this.CmdHandler.setAttribute("webContextMenu", '1');
          else
            this.CmdHandler.setAttribute("webContextMenu", '0');
          break;
        case "NotifyWhenBackbround":
          this.buf.notifyWhenBackbround=branch.getBoolPref(name);
          break;
        case "NotifyBySound":
          this.buf.notifyBySound=branch.getBoolPref(name);
          break;
        case "NotifyByMessage":
          this.buf.notifyByMessage=branch.getBoolPref(name);
          break;
        case "HideBookMarkLinkMenu":
          if(branch.getBoolPref(name))
            this.CmdHandler.setAttribute("hideBookMarkLink", '1');
          else
            this.CmdHandler.setAttribute("hideBookMarkLink", '0');
          break;
        case "HideSendLinkMenu":
          if(branch.getBoolPref(name))
            this.CmdHandler.setAttribute("hideSendLink", '1');
          else
            this.CmdHandler.setAttribute("hideSendLink", '0');
          break;
        case "HideBookMarkPageMenu":
          if(branch.getBoolPref(name))
            this.CmdHandler.setAttribute("hideBookMarkPage", '1');
          else
            this.CmdHandler.setAttribute("hideBookMarkPage", '0');
          break;
        case "HideSendPageMenu":
          if(branch.getBoolPref(name))
            this.CmdHandler.setAttribute("hideSendPage", '1');
          else
            this.CmdHandler.setAttribute("hideSendPage", '0');
          break;
        case "HideViewInfoMenu":
          if(branch.getBoolPref(name))
            this.CmdHandler.setAttribute("hideViewInfo", '1');
          else
            this.CmdHandler.setAttribute("hideViewInfo", '0');
          break;
        case "HideInputBuffer":
          this.view.hideInputBuffer = branch.getBoolPref(name);
          if(!this.view.hideInputBuffer)
          {
            this.DocInputArea.style.border = 'none';
            this.DocInputArea.style.width =  '200px';
            this.DocInputArea.style.height = '24px';
            this.DocInputArea.style.top = '0px';
            this.DocInputArea.style.left = '-10000px';
          }
          break;
        case "InputBufferSizeType":
          this.view.inputBufferSizeType = branch.getIntPref(name);
          break;
        case "DefineInputBufferSize":
          this.view.defineInputBufferSize = branch.getIntPref(name);
          break;
        case "UseKeyWordTrack":
          if(branch.getBoolPref(name))
          {
            this.CmdHandler.setAttribute("useKeyWordTrack", '1');
            this.view.useKeyWordTrack = true;
          }
          else
          {
            this.CmdHandler.setAttribute("useKeyWordTrack", '0');
            this.view.useKeyWordTrack = false;
          }
          this.view.redraw(true);
          this.view.updateCursorPos();
          break;
        case "DeleteSpaceWhenCopy":
          this.deleteSpaceWhenCopy=branch.getBoolPref(name);
          break;
        case "PushThreadLineLength":
          this.pushThreadLineLength = branch.getIntPref(name);
          break;
        case "EnablePicturePreview":
          this.view.enablePicturePreview = branch.getBoolPref(name);
          break;
        case "CtrlPicturePreview":
          this.view.ctrlPicturePreview = branch.getBoolPref(name);
          break;
        case "PicturePreviewInfo":
          this.view.picturePreviewInfo = branch.getBoolPref(name);
          break;
        case "PicturePreviewHeight":
          this.view.picturePreviewHeight = branch.getIntPref(name);
          this.CmdHandler.setAttribute('LastPicAddr', '0');
          break;
        case "preloginprompt":
          var str = pref.getPrefValue(name);
          this.telnetCore.loginPrompt[0] = this.buf.parseText(str);
          break;
        case "loginprompt":
          var str = pref.getPrefValue(name);
          this.telnetCore.loginPrompt[1] = this.buf.parseText(str);
          break;
        case "passwordprompt":
          var str = pref.getPrefValue(name);
          this.telnetCore.loginPrompt[2] = this.buf.parseText(str);
          break;
        case "prelogin":
          var str = pref.getPrefValue(name);
          this.telnetCore.loginStr[0] = this.buf.parseText(str);
          break;
        case "postlogin":
          var str = pref.getPrefValue(name);
          this.telnetCore.loginStr[3] = this.buf.parseText(str);
          break;
        case "login":
          var str = pref.getPrefValue(name);
          this.telnetCore.loginStr[1] = this.buf.parseText(str);
          break;
        case "passwd":
          var str = pref.getPrefValue(name);
          this.telnetCore.loginStr[2] = this.buf.parseText(str);
          break;
//
        case DISPLAY_BORDER:
        case BORDER_COLOR:
          var borderColor = pref.getPrefValue(BORDER_COLOR);
          if(pref.getPrefValue(DISPLAY_BORDER))
            this.view.mainDisplay.style.border = '1px solid '+termColors[borderColor];
          else
            this.view.mainDisplay.style.border = '0px';
          break;
        case "backgroundbrightness":
          var brightness = pref.getPrefValue(name);
          if(brightness == 100)// no alpha
            this.BBSBg.style.opacity = '1';
          else
            this.BBSBg.style.opacity = '0.' + (brightness);
          break;
        case "backgroundtype":
        case "backgrounddata":
          var bt = pref.getPrefValue("backgroundtype");
          var str = pref.getPrefValue("backgrounddata");//branch.getComplexValue('BackgroundImageMD5', CiStr).data;
          if(bt!=0 && str!='')
          {
            try
            {
              this.BBSBg.style.backgroundImage='url('+str+')';

              if(bt==4)
              {
                if(this.FXVersion >= 4.0) //for firefox 4
                  this.BBSBg.style.backgroundSize='100% 100%';
                else
                  this.BBSBg.style.MozBackgroundSize='100% 100%';
                this.BBSBg.style.backgroundPosition='left top';
                this.BBSBg.style.backgroundRepeat='no-repeat';
              }
              else if(bt==3)
              {
                if(this.FXVersion >= 4.0) //for firefox 4
                  this.BBSBg.style.backgroundSize='cover';
                else
                  this.BBSBg.style.MozBackgroundSize='cover';
                this.BBSBg.style.backgroundPosition='left top';
                this.BBSBg.style.backgroundRepeat='no-repeat';
              }
              else if(bt==2)
              {
                if(this.FXVersion >= 4.0) //for firefox 4
                  this.BBSBg.style.backgroundSize='auto auto';
                else
                  this.BBSBg.style.MozBackgroundSize='auto auto';
                this.BBSBg.style.backgroundPosition='center center';
                this.BBSBg.style.backgroundRepeat='no-repeat';
              }
              else if(bt==1)
              {
                if(this.FXVersion >= 4.0) //for firefox 4
                  this.BBSBg.style.backgroundSize='auto auto';
                else
                  this.BBSBg.style.MozBackgroundSize='auto auto';
                this.BBSBg.style.backgroundPosition='center center';
                this.BBSBg.style.backgroundRepeat='repeat';
              }
            }
            catch(ex)
            {
              bt=0;
            }
            //try to load picture, if load fail, set bt = 0;
          }
          if(bt==0)
          {
            this.BBSBg.style.display='none';
            this.CmdHandler.setAttribute("EnableBackground", '0');
            this.view.DisplayBackground=true;
            this.view.BackgroundMD5='';
          }
          else
          {
            this.BBSBg.style.display='block';
            this.CmdHandler.setAttribute("EnableBackground", '1');
            this.view.DisplayBackground=true;
          }
          break;
//
        case HOKEY_FOR_BG_DISPLAY:
          this.view.hokeyForBgDisplay = pref.getPrefValue(name);
          break;
        case "SwitchBgDisplayMenu":
          if(branch.getBoolPref(name))
            this.CmdHandler.setAttribute("SwitchBgDisplayMenu", '1');
          else
            this.CmdHandler.setAttribute("SwitchBgDisplayMenu", '0');
          break;
        }
      } catch(e) {
        // eats all errors
        return;
      }
    },

    /*
    doSiteSettingCheck: function(t) {
        if(this.settingCheckTimer)
          this.settingCheckTimer.cancel();
        var _this=this;
        var func=function() {
                this.settingCheckTimer = null;
                this.siteSettingCheck();
        }
        this.settingCheckTimer = this.view.myTimer(false, func, t);
    },
    */
    checkClass: function(cn) {
      return (  cn.indexOf("closeSI") >=0  || cn.indexOf("EPbtn") >= 0
             || cn.indexOf("closePP") >= 0 || cn.indexOf("picturePreview") >= 0
             || cn.indexOf("drag") >= 0    || cn.indexOf("floatWindowClientArea") >= 0
             || cn.indexOf("WinBtn") >= 0  || cn.indexOf("sBtn") >= 0
             || cn.indexOf("nonspan") >= 0 );
    },

    cancelDownloadAndPaste: function() {
      var rtn = false;
      if(this.DelayPasteBuffer != '' || this.DelayPasteIndex != -1)
      {
        this.DelayPasteBuffer = '';
        this.DelayPasteIndex = -1;
        //this.view.showAlertMessage(document.title, this.getLM('delayPasteStop'));
        rtn=true;
      }
      if(this.downpostcounter) {
        //this.downpostcounter.cancel();
        this.downpostcounter = null;
        this.post_text = new Array();
        this.post_html = new Array();
        this.view.doBlink = true;
        //this.view.showAlertMessage(document.title, this.getLM('alert_down_terminate'));
        rtn=true;
      }
      return rtn;
    },

    mouse_click: function(event) {

      var skipMouseClick = (this.CmdHandler.getAttribute('SkipMouseClick')=='1');
      this.CmdHandler.setAttribute('SkipMouseClick','0');
      if(this.cancelDownloadAndPaste())
        return;

      if(event.button==2) //right button
      {
      }
      else if(event.button==0) //left button
      {
        if(event.target && event.target.getAttribute("link")=='true')
        {
          return;
        }
        if(window.getSelection().isCollapsed) //no anything be select
        {
          if(this.buf.useMouseBrowsing)
          {
            var doMouseCommand = true;
            if(event.target.className)
              if(this.checkClass(event.target.className))
                doMouseCommand = false;
            if(event.target.tagName)
              if(event.target.tagName.indexOf("menuitem") >= 0 )
                doMouseCommand = false;
            if(skipMouseClick)
            {
              doMouseCommand = false;
              var pos = this.clientToPos(event.clientX, event.clientY);
              this.buf.onMouse_move(pos.col, pos.row, true);
            }
            if(doMouseCommand)
            {
                this.onMouse_click(event.clientX, event.clientY);
                this.setDblclickTimer();
                event.preventDefault();
                this.setInputAreaFocus();
            }
          }
        }
      }
      else if(event.button==1) //middle button
      {
        if(event.target && event.target.parentNode)
        {
          if(event.target.getAttribute("link")=='true')
            return;
        }
        if(this.view.middleButtonFunction==1)
          this.telnetCore.send('\r');
        else if(this.view.middleButtonFunction==2)
        {
          this.buf.SetPageState();
          if(this.buf.PageState==2 || this.buf.PageState==3 || this.buf.PageState==4)
            this.telnetCore.send('\x1b[D');
        }
      }
      else
      {
      }
    },

    mouse_down_init: function(event) {
      this.CmdHandler.setAttribute('mouseOnPicWindow','0');
    },

    mouse_down: function(event) {
      //0=left button, 1=middle button, 2=right button
      if(event.button==0)
      {
        if(this.buf.useMouseBrowsing)
        {
          if(this.dblclickTimer) //skip
          {
            event.preventDefault();
            event.stopPropagation();
            event.cancelBubble = true;
          }
          this.setDblclickTimer();
        }
        this.mouseLeftButtonDown = true;
        //this.setInputAreaFocus();
        if(!(window.getSelection().isCollapsed))
          this.CmdHandler.setAttribute('SkipMouseClick','1');

        var onbbsarea = true;
        if(event.target.className)
          if(this.checkClass(event.target.className))
            onbbsarea = false;
        if(event.target.tagName)
          if(event.target.tagName.indexOf("menuitem") >= 0 )
            onbbsarea = false;
        // Press left key for 1 sec
        this.cancelMouseDownTimer();
        //this.mouseDownTimeout = false;
        if(window.getSelection().isCollapsed && this.buf.useMouseBrowsing && this.view.useMouseBrowseSendEnter && onbbsarea) {
          var _this = this;
          var func = function() {
            clearTimeout(_this.mouseDownTimer);
            if(_this.mouseLeftButtonDown && window.getSelection().isCollapsed)
              _this.telnetCore.send(_this.view.EnterChar);
            _this.mouseDownTimer = null;
            _this.CmdHandler.setAttribute('SkipMouseClick','1');
          }
          this.mouseDownTimer = setTimer(false, func, 1000);
        }
      }
      else if(event.button==2)
      {
        this.mouseRightButtonDown = true;
    //create context menu
    this.resetMenuItems();
      }
    },

    mouse_up: function(event) {
      //0=left button, 1=middle button, 2=right button
      if(event.button==0)
      {
        this.cancelMouseDownTimer();
        this.setMbTimer();
        //this.CmdHandler.setAttribute('MouseLeftButtonDown', '0');
        this.mouseLeftButtonDown = false;
      }
      else if(event.button==2)
      {
        this.mouseRightButtonDown = false;
        //this.CmdHandler.setAttribute('MouseRightButtonDown', '0');
      }
      if(event.button==0 || event.button==2) //left or right button
      {
          if(window.getSelection().isCollapsed) //no anything be select
          {
            if(this.buf.useMouseBrowsing)
              this.onMouse_move(event.clientX, event.clientY);

            this.setInputAreaFocus();
            if(event.button==0)
            {
              var preventDefault = true;
              if(event.target.className)
                if(this.checkClass(event.target.className))
                  preventDefault = false;
              if(event.target.tagName)
                if(event.target.tagName.indexOf("menuitem") >= 0 )
                  preventDefault = false;
              if(preventDefault)
                event.preventDefault();
            }
          }
          else //something has be select
          {
            //document.getElementById('t').disabled="disabled"; //prevent input area get focus, if it get focus, select area will disappear
            //bbsfox.clearHighlight(); don't do this
            //document.getElementById('t').focus(); // if re-set focuse to input area, select area will disappear
          }
      }
      else
      {
        this.setInputAreaFocus();
        event.preventDefault();
      }
      var _this = this;
      var func = function() {
        clearTimeout(_this.focusTimer);
        _this.focusTimer = null;
        if(window.getSelection().isCollapsed)
          _this.setInputAreaFocus();
      }
      this.focusTimer = setTimer(false, func, 10);
      //if(event.button==2)
      //  this.checkFireGestureKey();
    },

    mouse_move: function(event) {
      this.view.tempPicX = event.clientX;
      this.view.tempPicY = event.clientY;
      //if we draging window, pass all detect.
      if(this.playerMgr && this.playerMgr.dragingWindow)
      {
        var dW = this.playerMgr.dragingWindow;
        if(this.CmdHandler.getAttribute("DragingWindow")=='1') {
          dW.playerDiv.style.left = dW.tempCurX + (event.pageX - dW.offX) + 'px';
          dW.playerDiv.style.top = dW.tempCurY + (event.pageY - dW.offY) + 'px';
          event.preventDefault();
          return;
        }
        else if(this.CmdHandler.getAttribute("DragingWindow")=='2') {
          dW.playerDiv2.style.left = dW.tempCurX + (event.pageX - dW.offX) + 'px';
          dW.playerDiv2.style.top = dW.tempCurY + (event.pageY - dW.offY) + 'px';
          event.preventDefault();
          return;
        }
      }
      else if(this.picViewerMgr && this.picViewerMgr.dragingWindow)
      {
        var dW = this.picViewerMgr.dragingWindow;
        dW.viewerDiv.style.left = dW.tempCurX + (event.pageX - dW.offX) + 'px';
        dW.viewerDiv.style.top = dW.tempCurY + (event.pageY - dW.offY) + 'px';
        event.preventDefault();
        return;
      }
      else if(this.symbolinput && this.symbolinput.dragingWindow)
      {
       var dW = this.symbolinput.dragingWindow;
       if(this.CmdHandler.getAttribute("DragingWindow")=='3') {
          dW.mainDiv.style.left = dW.tempCurX + (event.pageX - dW.offX) + 'px';
          dW.mainDiv.style.top = dW.tempCurY + (event.pageY - dW.offY) + 'px';
          event.preventDefault();
          return;
        }
      }
      //
      if(event.target.className)
      {
        if(event.target.className.indexOf("q")>=0){
          if(this.view.enablePicturePreview && (this.view.ctrlPicturePreview==false || (this.view.ctrlPicturePreview && event.ctrlKey)  ) )
          {
            //if(e.target.rel.toLowerCase() == "p")
            var url = null;// = event.target.parentNode.getAttribute("href");
            var hrel = null;// = event.target.parentNode.getAttribute("rel");
            var node = event.target;
            if(node.getAttribute("link")=='true')
            {
              while(node.parentNode && !url)
              {
                node = node.parentNode;
                url = node.getAttribute("href");
                hrel = node.getAttribute("rel");
              }
            }
            if(hrel && hrel.toLowerCase()=='p'
              && url.toLowerCase().indexOf("http://photo.xuite.net/")<0
              && url.toLowerCase().indexOf("http://simplest-image-hosting.net/")<0
              && url.toLowerCase().indexOf("http://screensnapr.com/")<0)
            {
              this.setPicLocation(event.clientX, event.clientY);
              this.view.pictureWindow.style.display = "block";
              if(this.CmdHandler.getAttribute('LastPicAddr') == url){
                //if(this.view.picturePreviewInfo)
                //  this.view.pictureInfoLabel.style.display='inline';
                //else
                //  this.view.pictureInfoLabel.style.display='none';
              }else{
                this.view.picturePreview.innerHTML = "";
                this.view.picturePreview.style.display = "none";
                this.view.pictureInfoLabel.style.display = "none";
                this.view.picLoadingImage.src="chrome://bbsfox/skin/state_icon/connecting.gif";
                this.view.picturePreviewLoading.style.display = "block";
                this.CmdHandler.setAttribute('LastPicAddr', url);
                var image = document.createElement('img');
                this.view.picturePreview.appendChild(image);
                image.onload = function(){
                   bbsfox.prePicResize(this);
                };
                image.onerror = function(){
                   bbsfox.picLoaderror(this);
                };
                image.setAttribute('src',url);
              }
            }
          }
        }
        //fix bug while no mouseout event to hide img
        else// if(e.target.tagName.toLowerCase() == "img")
        {
          //this.view.pictureWindow.style.display = "none";
        }
      }//end of if(e.target.className)

      if(this.buf.useMouseBrowsing)
      {
        if(window.getSelection().isCollapsed)
        {
          if(!this.mouseLeftButtonDown)
            this.onMouse_move(event.clientX, event.clientY);
        }
        else
          this.resetMouseCursor();
      }
    },

    mouse_over: function(event) {
      if(window.getSelection().isCollapsed && !this.mouseLeftButtonDown)
        this.setInputAreaFocus();
    },

    mouse_scroll:function(event) {
          var cmdhandler = this.CmdHandler;
          //if(!cmdhandler)
          //  return;

          var mouseWheelFunc1 = cmdhandler.getAttribute(MOUSE_WHEEL_FUNC1);//useMouseUpDown
          var mouseWheelFunc2 = cmdhandler.getAttribute(MOUSE_WHEEL_FUNC2);//useMouseSwitchPage
          var mouseWheelFunc3 = cmdhandler.getAttribute(MOUSE_WHEEL_FUNC3);//useMouseReadThread

          var useMouseWheelFunc1 = (mouseWheelFunc1!='0');
          var useMouseWheelFunc2 = (mouseWheelFunc2!='0');
          var useMouseWheelFunc3 = (mouseWheelFunc3!='0');
          if(useMouseWheelFunc1 || useMouseWheelFunc2 || useMouseWheelFunc3) {
            //var curApp = this.view.cursorAppMode;
            if(event.wheelDelta > 0)
            {
              if(this.mouseRightButtonDown)
              {
                if(useMouseWheelFunc2)
                {
                  if(mouseWheelFunc2=='1')
                    this.setBBSCmd('doArrowUp', cmdhandler);
                  else if(mouseWheelFunc2=='2')
                    this.setBBSCmd('doPageUp', cmdhandler);
                  else if(mouseWheelFunc2=='3')
                    this.setBBSCmd('prevousThread', cmdhandler);
                  event.stopPropagation();
                  event.preventDefault();
                }
              }
              else if(this.mouseLeftButtonDown)
              {
                if(useMouseWheelFunc3)
                {
                  if(mouseWheelFunc3=='1')
                    this.setBBSCmd('doArrowUp', cmdhandler);
                  else if(mouseWheelFunc3=='2')
                    this.setBBSCmd('doPageUp', cmdhandler);
                  else if(mouseWheelFunc3=='3')
                    this.setBBSCmd('prevousThread', cmdhandler);
                  this.setBBSCmd('cancelHoldMouse', cmdhandler);
                  event.stopPropagation();
                  event.preventDefault();
                }
              }
              else if(useMouseWheelFunc1)
              {
                if(mouseWheelFunc1=='1')
                  this.setBBSCmd('doArrowUp', cmdhandler);
                else if(mouseWheelFunc1=='2')
                  this.setBBSCmd('doPageUp', cmdhandler);
                else if(mouseWheelFunc1=='3')
                  this.setBBSCmd('prevousThread', cmdhandler);
                event.stopPropagation();
                event.preventDefault();
              }
            }
            else
            {
              if(this.mouseRightButtonDown)
              {
                if(useMouseWheelFunc2)
                {
                  if(mouseWheelFunc2=='1')
                    this.setBBSCmd('doArrowDown', cmdhandler);
                  else if(mouseWheelFunc2=='2')
                    this.setBBSCmd('doPageDown', cmdhandler);
                  else if(mouseWheelFunc2=='3')
                    this.setBBSCmd('nextThread', cmdhandler);
                  event.stopPropagation();
                  event.preventDefault();
                }
              }
              else if(this.mouseLeftButtonDown)
              {
                if(useMouseWheelFunc3)
                {
                  if(mouseWheelFunc3=='1')
                    this.setBBSCmd('doArrowDown', cmdhandler);
                  else if(mouseWheelFunc3=='2')
                    this.setBBSCmd('doPageDown', cmdhandler);
                  else if(mouseWheelFunc3=='3')
                    this.setBBSCmd('nextThread', cmdhandler);
                  this.setBBSCmd('cancelHoldMouse', cmdhandler);
                  event.stopPropagation();
                  event.preventDefault();
                }
              }
              else if(useMouseWheelFunc1)
              {
                if(mouseWheelFunc1=='1')
                  this.setBBSCmd('doArrowDown', cmdhandler);
                else if(mouseWheelFunc1=='2')
                  this.setBBSCmd('doPageDown', cmdhandler);
                else if(mouseWheelFunc1=='3')
                  this.setBBSCmd('nextThread', cmdhandler);
                event.stopPropagation();
                event.preventDefault();
              }
            }
            if(this.mouseRightButtonDown && useMouseWheelFunc2) //prevent context menu popup
              cmdhandler.setAttribute('doDOMMouseScroll','1');
            if(this.mouseLeftButtonDown && useMouseWheelFunc3)
            {
              if(cmdhandler.getAttribute(USE_MOUSE_BROWSING)=='1')
              {
                cmdhandler.setAttribute('SkipMouseClick','1');
              }
            }
          }
    },

    context_menu: function(event) {
          var cmdhandler = this.CmdHandler;
          var mouseWheelFunc2 = (cmdhandler.getAttribute(MOUSE_WHEEL_FUNC2)!='0');
          if(mouseWheelFunc2)
          {
            var doDOMMouseScroll = (cmdhandler.getAttribute('doDOMMouseScroll')=='1');
            if(doDOMMouseScroll)
            {
              event.stopPropagation();
              event.preventDefault();
              cmdhandler.setAttribute('doDOMMouseScroll','0');
            }
            else
            {
            }
          }
          else
          {
          }
    },

    /*
    mouse_dragover: function(event) {
      this.cancelMouseDownTimer();
      var dt = event.dataTransfer;
      var isLink = dt.types.contains("text/uri-list");
      var isText = dt.types.contains("text/plain");
      var isFile = dt.types.contains("application/x-moz-file");
      //           dt.mozSetDataAt("application/x-moz-file", file, 0);
      //file: (1)text file, copy and paste file to BBS (not support yet)
      //      (2)binery file, auto upload to web HDD and return a link (not support yet)
      if (isLink || isText)
      {
        dt.dropEffect = "copy";
        event.preventDefault();
      }
      else if(isFile)
      {
        var file = dt.mozGetDataAt("application/x-moz-file", 0);
        if (file instanceof Components.interfaces.nsIFile)
        {
          //do default action(or we check 'xpi' for install, other for upload);
        }
        else
        {
          dt.dropEffect = "none";
          event.preventDefault();
        }
      }
      else
      {
        dt.dropEffect = "none";
        event.preventDefault();
      }
    },

    mouse_dragdrop: function(event) {
      var dt = event.dataTransfer;
      var isLink = dt.types.contains("text/uri-list");
      var isText = dt.types.contains("text/plain");
      //if URL or Text is a Youtube/UStream link, maybe we can open Player Window
      if(isLink || isText)
      {
        var str;
        if(isLink)
          str = dt.getData("URL");
        else if(isText)
          str = dt.getData("text/plain");
        if(this.playerMgr.epWhenDropLink)
        {
          if(this.youtubeRegEx.test(str))
          {
            this.playerMgr.openYoutubeWindow(str);
            event.preventDefault();
            this.setDelayInputAreaFocus();
            return;
          }
          else if(this.ustreamRegEx.test(str))
          {
            this.playerMgr.openUstreamWindow(str);
            event.preventDefault();
            this.setDelayInputAreaFocus();
            return;
          }
          else if(this.urecordRegEx.test(str))
          {
            this.playerMgr.openUrecordWindow(str);
            event.preventDefault();
            this.setDelayInputAreaFocus();
            return;
          }
        }
        if(this.view.dropToPaste)
          this.doPasteStr(str);
        event.preventDefault();
      }
      this.setDelayInputAreaFocus();
    },
    */
    key_press: function(event) {
      if(this.cancelDownloadAndPaste())
      {
        event.preventDefault();
        event.stopPropagation();
        return;
      }
      if(event.charCode){
        // Control characters
        if(event.ctrlKey && !event.altKey && !event.shiftKey && (event.charCode == 99 || event.charCode == 67) && !window.getSelection().isCollapsed && this.view.hokeyForCopy) { //^C , do copy
          //this.doCopySelect();
          event.preventDefault();
          event.stopPropagation();
          return;
        }
        else if(event.ctrlKey && !event.altKey && !event.shiftKey && (event.charCode == 100 || event.charCode == 68) && this.view.hokeyForDownloadPost) { //^D , do download post
          //if(this.view.hotkeyDownloadType==0)
          //  this.downloadPost(false,false,false);
          //if(this.view.hotkeyDownloadType==1)
          //  this.downloadPost(true,false,false);
          //else
          //  this.downloadPost(true,true,false);
          event.preventDefault();
          event.stopPropagation();
        }
        else if(event.ctrlKey && !event.altKey && !event.shiftKey && (event.charCode == 101 || event.charCode == 69) && this.view.hokeyForBgDisplay) { //^E , switch background display
          //this.switchBgDisplay();
          event.preventDefault();
          event.stopPropagation();
        }
        else if(event.ctrlKey && !event.altKey && !event.shiftKey && (event.charCode == 103 || event.charCode == 71) && this.view.hokeyForEasyReading) { //^G , easy reading mode
          //this.downloadPost(true,true,true);
          event.preventDefault();
          event.stopPropagation();
        }
        else if(event.ctrlKey && !event.altKey && !event.shiftKey && event.charCode == 46) { //Alt + ^+, do add Track word
          //this.doAddTrack();
          event.preventDefault();
          event.stopPropagation();
        }
        else if(event.ctrlKey && !event.altKey && !event.shiftKey && event.charCode == 44) { //Alt + ^-, do del Track word
          //this.doDelTrack();
          event.preventDefault();
          event.stopPropagation();
        }
        if(window.getSelection().isCollapsed)
          this.setInputAreaFocus();
      }
      else
      {
        if(window.getSelection().isCollapsed)
          this.setInputAreaFocus();
      }
    },
    /*
    setPicLocation: function(curx, cury) {
      var bbswinwidth = parseFloat(this.buf.BBSWin.style.width);
      var bbswinheight = parseFloat(this.buf.BBSWin.style.height);
      var newleft;
      var newtop;
      if(curx + this.view.tempIamgeWidth < bbswinwidth)
        newleft = curx + 15;
      else
        newleft = curx - (this.view.tempIamgeWidth+5);

      if(newleft+this.view.tempIamgeWidth > bbswinwidth) newleft = bbswinwidth-this.view.tempIamgeWidth;
      if(newleft<0) newleft = 0;
      this.view.pictureWindow.style.left = newleft +"px";

      if(cury > this.view.tempIamgeHeight)
        newtop = cury - this.view.tempIamgeHeight;
      else
        newtop = cury + 5;

      if(newtop+this.view.tempIamgeHeight> bbswinheight) newtop = bbswinheight-this.view.tempIamgeHeight;
      if(newtop<0) newtop = 0;
      this.view.pictureWindow.style.top = newtop +"px";
    },

    picLoaderror: function(img) {
      if(this.view.ictureWindow.style.display == "block")
      {
        this.view.picLoadingImage.src="icon/error.png";
        this.view.picturePreviewLoading.style.display = "block";
        this.view.picturePreview.style.display = "none";
        this.view.tempIamgeWidth = 40;
        this.view.tempIamgeHeight = 40;
      }
      else
      {
      }
      this.CmdHandler.setAttribute('LastPicAddr', '');
    },

    prePicResize: function(img) {
      if(this.view.pictureWindow.style.display == "block")
      {
        this.view.picturePreviewLoading.style.display = "none";
        this.view.picturePreview.style.display = "block";
        var imgWidth = parseFloat(document.defaultView.getComputedStyle(img, null).width);
        var imgHeight = parseFloat(document.defaultView.getComputedStyle(img, null).height);
        var scale = 0;
        if(this.view.picturePreviewHeight>0)
          scale = imgHeight / this.view.picturePreviewHeight;
        if(scale > 1) {
          img.style.width = imgWidth / scale + "px";
          img.style.height = imgHeight / scale + "px";
          this.view.pictureInfoLabel.innerHTML=imgWidth+' x '+imgHeight+' ('+ Math.floor(100 / scale) +'%)';
          if(this.view.picturePreviewInfo)
            this.view.pictureInfoLabel.style.display='inline';
          this.view.tempIamgeWidth = (imgWidth / scale) +25;
          this.view.tempIamgeHeight = (imgHeight / scale) +25;
        }
        else{
          this.view.tempIamgeWidth = imgWidth+25;
          this.view.tempIamgeHeight = imgHeight+25;
          this.view.pictureInfoLabel.innerHTML=imgWidth+' x '+imgHeight+' (100%)';
          if(this.view.picturePreviewInfo)
            this.view.pictureInfoLabel.style.display='inline';
        }
        this.setPicLocation(this.view.tempCurX, this.view.tempCurY);
      }
      else
      {
        this.CmdHandler.setAttribute('LastPicAddr', '');
      }
    },
    */
    downloadPost: function(iscolor, htmlmode, newtab){
        var anciCmp = false;
        var finished = false;
        var percentage = -1;
        for(var col = 0; col < this.buf.cols; ++col) {
            if(this.buf.lines[this.buf.rows-1][col].ch == '%') {
                percentage = col;
                break;
            }
        }
        var initial = (!this.post_text || !this.post_text.length);
        if(initial) { // initialize
            this.post_text = new Array();
            this.post_html = new Array();
            if(htmlmode)
            {
              this.view.doBlink = false;
              this.view.blinkOn = true;
              this.view.update();
              for(var row = 0; row < this.buf.rows-1; ++row)
                this.post_html.push('<span class="BBSLine">'+this.view.BBSROW[row].innerHTML+'</span><br>');
            }
            for(var row = 0; row < this.buf.rows-1; ++row)
                this.post_text.push(this.buf.getText(row, 0, this.buf.cols, true, true));
            if(this.downpostcounter) {
                this.downpostcounter.cancel();
                this.downpostcounter = null;
            }
            var _this=this;
            this.downpostcounter = setTimer(true, function(){_this.downloadPost(iscolor, htmlmode, newtab);}, this.buf.downloadLineDelay);
        }
        // mark for finishing download
        if(percentage < 3 || (this.buf.lines[this.buf.rows-1][percentage-3].ch == '1' && this.buf.lines[this.buf.rows-1][percentage-2].ch == '0')) {
            finished = true;
            this.downpostcounter.cancel();
            this.downpostcounter = null;
        }
        if(initial && !finished) { // start scrolling
            //this.telnetCore.send(this.view.cursorAppMode?'\x1bOB':'\x1b[B');
            this.buf.downPostChanged = false;
            this.telnetCore.send('\x1b[B');
            return;
        } else if(initial); // finished, exit this conditional block
        else if(this.buf.cur_y < this.buf.rows-1 || this.buf.cur_x <= percentage || !this.buf.downPostChanged)
            return; // Wait for the new line to be received in full
        else {
            // modification for PTT
            // i is kept after this loop as the number of the repeated lines
            var buflen = this.post_text.length;
            var bufstr = this.post_text[buflen-1];
            if(!anciCmp) bufstr = bufstr.replace(/\x1b\[[0-9;]*m/g, '');
            for(var i = 1; i <= this.buf.rows-2; ++i) {
                if(!anciCmp && this.post_text[buflen-1-i].replace(/\x1b\[[0-9;]*m/g, '') != bufstr) break;
                if(anciCmp && this.post_text[buflen-1-i] != bufstr) break;
            }
            // find how many lines are needed to be appended
            var k = this.buf.rows - 1;
            for(var j = this.buf.rows-i-2; j >= 1; --j) {
                if(htmlmode)
                  this.post_html.splice(buflen, 0, '<span class="BBSLine">'+this.view.BBSROW[k-1].innerHTML+'</span><br>');
                this.post_text.splice(buflen, 0, this.buf.getText(--k, 0, this.buf.cols, true, true));
                var thisline = this.buf.getText(j, 0, this.buf.cols, true, true);
                var preline = this.buf.getText(j-1, 0, this.buf.cols, true, true);
                if(!anciCmp) {
                    thisline = thisline.replace(/\x1b\[[0-9;]*m/g, '');
                    preline = preline.replace(/\x1b\[[0-9;]*m/g, '');
                }
                if(thisline.indexOf(bufstr) >= 0 && preline.indexOf(bufstr) < 0) break;
            }
            // detection failed, guess how many lines were scrolled unreliably
            if(j <= 0) {
                for(var l = 0; l < this.buf.rows-1; ++l) {
                    if(!anciCmp && this.buf.getText(l, 0, this.buf.cols, true, true).replace(/\x1b\[[0-9;]*m/g, '') != bufstr) break;
                    if(anciCmp && this.buf.getText(l, 0, this.buf.cols, true, true) != bufstr) break;
                }
                if(this.buf.rows-i-2 > 0) l += this.buf.rows-i-2; // unchecked
                while(--k >= 0) {
                    var thisline = this.buf.getText(k, 0, this.buf.cols, true, true);
                    var thisline2 = '<span class="BBSLine">'+this.view.BBSROW[k].innerHTML+'</span><br>';
                    if(++l < this.buf.rows)
                    {
                      if(htmlmode)
                        this.post_html.splice(buflen, 0, thisline2);
                      this.post_text.splice(buflen, 0, thisline);
                    }
                    else break;
                }
            }
            if(!finished) {
                //this.telnetCore.send(this.view.cursorAppMode?'\x1bOB':'\x1b[B');
                this.buf.downPostChanged = false;
                this.telnetCore.send('\x1b[B');
            }
        }
        if(finished) { // finish download
            if(htmlmode)
            {
              var selstr='';
              var selstr2='';
              var fontFace = this.view.fontFace
              if(fontFace=="")
                fontFace = "MingLiu";
              selstr = '<?xml version="1.0" encoding="UTF-8"?><html><head><title></title><style type="text/css">';
              selstr += '.main {font-family: ';
              selstr += fontFace;
              selstr += ';font-size: ';
              selstr += this.view.chh;
              selstr += 'px;background-color: #000000;line-height: 100%; margin: 0px;textAlign:'
              selstr += this.view.mainDisplay.style.textAlign;
              selstr += ';width:';
              selstr += this.view.mainDisplay.style.width;
              //selstr += ';}body{color:white;background-color: #000000;margin:0px;}a,a:link,a:visited,a:active,a:hover{border-bottom: 1px solid #FF6600;text-decoration:none;}.BBSLine{display:inline;color:#C0C0C0;white-space: pre;}#BBSWindow{position:relative;}';
              //selstr += ';}body{color:white;background-color: #000000;margin:0px;}.BBSLine{display:inline;color:#C0C0C0;white-space: pre;}#BBSWindow{position:relative;}';
              selstr += ';}body{color:white;background-color: #000000;margin:0px;}';
              if(!this.view.easyReadingWithImg)
                selstr += 'a,a:link,a:visited,a:active,a:hover{border-bottom: 1px solid #FF6600;text-decoration:none;}';
              selstr += '.BBSLine{display:inline;color:#C0C0C0;white-space: pre;}#BBSWindow{position:relative;}';
              for(var i=0;i<16;++i)
                for(var j=0;j<16;++j)
                  selstr +='.q'+i+'b'+j+'{color:'+ termColors[i] + (j!=0?(';background-color:'+termColors[j]):'') + ';}';

              for(var i=0;i<16;++i)
                for(var j=0;j<16;++j)
                {
                  selstr +='.q'+i+'q'+j+'{color:'+ termColors[j] +';position:relative;}';
                  selstr +='.q'+i+'q'+j+':after{content:attr(t);position:absolute;left:0px;color:'+termColors[i]+';width:50%;text-shadow:'+termColors[i]+' 0 0 0px,'+termColors[i]+' 0 0 0px,'+termColors[i]+' 0 0 0px,'+termColors[i]+' 0 0 0px,'+termColors[i]+' 0 0 0px;overflow:hidden;}';
                }

              for(var i=0;i<16;++i)
                for(var j=0;j<16;++j)
                  selstr +='.b'+i+'b'+j+'{background:-moz-linear-gradient(left,'+termColors[i]+' 50%,'+termColors[j]+' 50%);}';

              for(var i=0;i<16;++i)
                selstr +='.q'+i+'{color:'+termColors[i]+';}';

              for(var i=1;i<16;++i)
                selstr +='.b'+i+'{background-color:'+termColors[i]+';}';

              //selstr += '</style></head><body><div id="BBSWindow"><div id="main" class="main">';
              selstr += '</style>';
              if(this.view.easyReadingWithImg)
                selstr += '<script>function insertImg() {var allLinks = document.getElementsByTagName("a");for (var i = 0; i < allLinks.length; i++){var url = allLinks[i].getAttribute("href");var hrel = allLinks[i].getAttribute("rel");if(hrel && hrel.toLowerCase()=="p" && url.toLowerCase().indexOf("http://photo.xuite.net/")<0 && url.toLowerCase().indexOf("http://simplest-image-hosting.net/")<0 && url.toLowerCase().indexOf("http://screensnapr.com/")<0){var br = document.createElement("BR");allLinks[i].appendChild(br);var img = document.createElement("img");allLinks[i].appendChild(img);img.setAttribute("src", url);}}}</script>';
              selstr += '</head><body';
              if(this.view.easyReadingWithImg)
                selstr += ' onload="insertImg()"';
              selstr += '><div id="BBSWindow"><div id="main" class="main">';
              selstr2 +='</div></div></body></html>';
              this.view.doBlink = true;
              var post_html = selstr + this.post_html.join('') + selstr2;
              if(newtab){
                var ios = Components.classes["@mozilla.org/network/io-service;1"].getService(Components.interfaces.nsIIOService);
                var filetmp = Components.classes["@mozilla.org/file/directory_service;1"].getService(Components.interfaces.nsIProperties).get("TmpD", Components.interfaces.nsIFile);
                filetmp.append('easyreading.htm');
                filetmp.createUnique(Components.interfaces.nsIFile.NORMAL_FILE_TYPE, 0666);
                var ostream = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance(Components.interfaces.nsIFileOutputStream);
                ostream.init(filetmp, -1, -1, 0);
                var converter = Components.classes["@mozilla.org/intl/converter-output-stream;1"].createInstance(Components.interfaces.nsIConverterOutputStream);
                converter.init(ostream, "UTF-8", 0, 0);
                converter.writeString(post_html);
                converter.flush();
                converter.close();
                var tempURI = ios.newFileURI(filetmp).spec;
                try{
                  var win = Components.classes["@mozilla.org/appshell/window-mediator;1"].getService(Components.interfaces.nsIWindowMediator).getMostRecentWindow("navigator:browser");
                  if(win)
                    win.gBrowser.loadOneTab(tempURI, null, 'UTF-8', null, true, false);
                  else
                    window.open(tempURI);
                }
                catch(e){
                }
                this.tempFiles.push(filetmp);
                //filetmp.remove(true);
              }
              else{
                this.doCopy(post_html);
              }
            }
            else
            {
              if(iscolor) var post_text = this.post_text.join('\r\n');
              else  var post_text = this.post_text.join('\r\n').replace(/\x1b\[[0-9;]*m/g, '');
              this.doCopy(post_text);
            }
            this.post_text = new Array();
            this.post_html = new Array();
            this.view.showAlertMessage(document.title, this.getLM('alert_down_finish'));
            if(this.buf.saveAfterDownload && !(htmlmode && newtab))
              this.buf.saveFile();
        }
    },
    /*
    cleanupTempFiles: function(event){
      for(var i=0;i<this.tempFiles.length;++i)
      {
        try{
          this.tempFiles[i].remove(true);
        }
        catch(e){
        }
      }
      this.tempFiles.length = 0;
    },
    */
    window_beforeunload: function(event){
      //event.returnValue = confirm('Are you sure you want to leave '+document.title+'?');
      event.returnValue = true;
      return document.title;
    },

    RegExitAlert: function(){
      this.UnregExitAlert();
      this.alertBeforeUnload = true;
      window.addEventListener('beforeunload', this.window_beforeunload, false);
    },

    UnregExitAlert: function(){
      // clear alert for closing tab
      if(this.alertBeforeUnload) {
        this.alertBeforeUnload = false;
        window.removeEventListener('beforeunload', this.window_beforeunload, false);
      }
    },
    /*
    bgtab: function (event, sender){
      if(this.loadURLInBG)
      {
        var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"].getService(Components.interfaces.nsIWindowMediator);
        var gBrowser = wm.getMostRecentWindow("navigator:browser").gBrowser;
        var newTab = gBrowser.addTab(sender.href, gBrowser.currentURI);
        event.stopPropagation();
        event.preventDefault();
      }
    },

    loadLoginData: function(){
      //var group = 'bbs.gamer.com.tw';
      var url = this.isDefaultPref ? 'chrome://bbsfox2' : 'telnet://' + document.location.hostname;
      try {
        var logins = Components.classes["@mozilla.org/login-manager;1"].getService(Components.interfaces.nsILoginManager).findLogins({}, url, 'chrome://bbsfox2', null);
        if(logins.length)
        {
          this.telnetCore.loginStr[1]=logins[0]['username'];
          this.telnetCore.loginStr[2]=logins[0]['password'];
        }
        else
        {
          this.telnetCore.loginStr[1]='';
          this.telnetCore.loginStr[2]='';
        }
      } catch(e) {
        this.telnetCore.loginStr[1]='';
        this.telnetCore.loginStr[2]='';
      }
    },

    doPushThread: function(){
      if(this.isPTT(document.location.hostname))
      {
        const EMURL = "chrome://bbsfox/content/pushThread.xul";
        const EMFEATURES = "chrome, dialog=yes, resizable=yes, modal=yes, centerscreen";
        var retVals = { exec: false, pushText: this.pushTextTemp, lineLength: this.pushThreadLineLength};
        var retVals2 = [];
        window.openDialog(EMURL, "", EMFEATURES, retVals, retVals2);
        if(retVals.exec)
        {
          for(var i =0;i<retVals2.length;++i)
          {
            this.telnetCore.convSend(retVals2[i], this.view.charset);
            this.telnetCore.send(this.view.EnterChar+'y'+this.view.EnterChar);
          }
        }
        else
        {
          this.pushTextTemp = retVals.pushText;
        }
      }
    }
    */
    setBBSCmd:function(cmd, cmdhandler) {
      //var doc = gBrowser.contentDocument;
      var doc = document;
      if(!cmdhandler)
        cmdhandler = this.getCmdHandler();

      if (cmdhandler && "createEvent" in doc) {
        cmdhandler.setAttribute('bbsfoxCommand', cmd);
        var evt = doc.createEvent("Events");
        evt.initEvent("OverlayCommand", false, false);
        cmdhandler.dispatchEvent(evt);
      }
    },

    createMenu: function(title, func, parentId, id) {
      var createProperties = { 
        "title": title, 
        "id": (id?id:title),
        "contexts": ["page", "selection"]
      };
      if(func)
        this.menuHandler[createProperties.id] = func;
      if(parentId)
        createProperties.parentId = parentId;

      return chrome.contextMenus.create(createProperties, function() {});
    },

    resetMenuItems: function pcmanMenuItems() {
      chrome.contextMenus.removeAll();
      // create the contentMenu item
      var popup_paste = this.createMenu(msg("menu_paste"), function() {
          bbsfox.doPaste();
      }, null, 'paste');
      var popup_selectAll = this.createMenu(msg("menu_selAll"), function() {
          bbsfox.doSelectAll();
      }, null, 'selectall');

    }
}
